// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/test/embedded_test_server/http_response.h"

#include "base/bind.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "net/http/http_status_code.h"

namespace net {
namespace test_server {

HttpResponse::~HttpResponse() = default;

RawHttpResponse::RawHttpResponse(const std::string& headers,
                                 const std::string& contents)
    : headers_(headers), contents_(contents) {}

RawHttpResponse::~RawHttpResponse() = default;

void RawHttpResponse::SendResponse(const SendBytesCallback& send,
                                   const SendCompleteCallback& done) {
  std::string response;
  if (!headers_.empty()) {
    response = headers_;
    // LocateEndOfHeadersHelper() searches for the first "\n\n" and "\n\r\n" as
    // the end of the header.
    std::size_t index = response.find_last_not_of("\r\n");
    if (index != std::string::npos)
      response.erase(index + 1);
    response += "\n\n";
    response += contents_;
  } else {
    response = contents_;
  }
  send.Run(response, done);
}

void RawHttpResponse::AddHeader(const std::string& key_value_pair) {
  headers_.append(base::StringPrintf("%s\r\n", key_value_pair.c_str()));
}

BasicHttpResponse::BasicHttpResponse() : code_(HTTP_OK) {
}

BasicHttpResponse::~BasicHttpResponse() = default;

std::string BasicHttpResponse::ToResponseString() const {
  // Response line with headers.
  std::string response_builder;

  std::string http_reason_phrase(GetHttpReasonPhrase(code_));

  // TODO(mtomasz): For http/1.0 requests, send http/1.0.
  base::StringAppendF(&response_builder,
                      "HTTP/1.1 %d %s\r\n",
                      code_,
                      http_reason_phrase.c_str());
  base::StringAppendF(&response_builder, "Connection: close\r\n");

  base::StringAppendF(&response_builder, "Content-Length: %" PRIuS "\r\n",
                      content_.size());
  base::StringAppendF(&response_builder, "Content-Type: %s\r\n",
                      content_type_.c_str());
  for (size_t i = 0; i < custom_headers_.size(); ++i) {
    const std::string& header_name = custom_headers_[i].first;
    const std::string& header_value = custom_headers_[i].second;
    DCHECK(header_value.find_first_of("\n\r") == std::string::npos) <<
        "Malformed header value.";
    base::StringAppendF(&response_builder,
                        "%s: %s\r\n",
                        header_name.c_str(),
                        header_value.c_str());
  }
  base::StringAppendF(&response_builder, "\r\n");

  return response_builder + content_;
}

void BasicHttpResponse::SendResponse(const SendBytesCallback& send,
                                     const SendCompleteCallback& done) {
  send.Run(ToResponseString(), done);
}

DelayedHttpResponse::DelayedHttpResponse(const base::TimeDelta delay)
    : delay_(delay) {}

DelayedHttpResponse::~DelayedHttpResponse() = default;

void DelayedHttpResponse::SendResponse(const SendBytesCallback& send,
                                       const SendCompleteCallback& done) {
  base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, base::BindOnce(send, ToResponseString(), done), delay_);
}

void HungResponse::SendResponse(const SendBytesCallback& send,
                                const SendCompleteCallback& done) {}

}  // namespace test_server
}  // namespace net
