blob: b1191f55af7babc7ffe1d1e013e2c12e49ee160a [file] [log] [blame]
// Copyright 2018 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVTOOLS_GOMA_CLIENT_HTTP_UTIL_H_
#define DEVTOOLS_GOMA_CLIENT_HTTP_UTIL_H_
// Utilities for HTTP.
// TODO: move http funcs from ioutil.
#include <cstddef>
#include <map>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
namespace devtools_goma {
const int kNetworkBufSize = 1024 * 32;
extern const absl::string_view kAcceptEncoding;
extern const absl::string_view kAuthorization;
extern const absl::string_view kContentEncoding;
extern const absl::string_view kContentLength;
extern const absl::string_view kContentType;
extern const absl::string_view kCookie;
extern const absl::string_view kHost;
extern const absl::string_view kUserAgent;
extern const absl::string_view kTransferEncoding;
// Extracts HTTP header field value.
// field_name should not have leading and trailing space.
// header should be HTTP message header, i.e. ends with CRLFCRLF.
// TODO: use this instead of header.find("field:")
absl::string_view ExtractHeaderField(
absl::string_view header, absl::string_view field_name);
// Parse the HTTP response header.
// Return true if it got all header, or error response.
// Return false if it needs more data.
//
// In case of returning true with error, |http_status_code| will not be
// 200 or 204. You must not use other fields in such a case.
//
// If returning true without error, followings could be set:
// |http_status_code| represents HTTP status code.
// |offset| represents offset where HTTP body starts.
// |content_length| represents value of Content-Length header if exists.
// If no Content-Length header found in the header, |content_length| is set to
// string::npos.
// |is_chunked| become true if HTTP response is sent with chunked transfer
// encoding. Note that the function will not check chunked transfer coding
// if |is_chunked| == NULL.
bool ParseHttpResponse(absl::string_view response,
int* http_status_code,
size_t* offset,
size_t* content_length,
bool* is_chunked);
// Parse HTTP request and response headers and return offset into body
// and content-length. Content-Length may be missing, and in that case
// content_length will be set to string::npos.
// If data is encoded with chunked transfer encoding, is_chunked will be
// set to true.
//
// Do not check chunked transfer coding if is_chunked == NULL.
bool FindContentLengthAndBodyOffset(
absl::string_view data, size_t *content_length, size_t *body_offset,
bool *is_chunked);
// Parse http request query parameter.
std::map<std::string, std::string> ParseQuery(const std::string& query);
// http://code.google.com/apis/chart/docs/data_formats.html#simple
std::string SimpleEncodeChartData(
const std::vector<double>& value, double max);
class HttpChunkParser {
public:
HttpChunkParser();
~HttpChunkParser() = default;
// Parse parses chunked transfer encoding from stream
// into *pieces, and returns true.
// All chunk-data in stream will be appended into *pieces.
// chunk-data may be several pieces, if boundary is in chunk-data.
// It returns false if it failed to parse chunked transfer encoding.
bool Parse(absl::string_view stream,
std::vector<absl::string_view>* pieces);
// Returns true if chunked transfer encoding is finished
// in the last Parse.
bool done() const {
return done_;
}
// Returns error message after Parse returns false.
const std::string& error_message() const {
return error_message_;
}
private:
// last_chunk_remain is a number of remaining bytes of the last chunk.
size_t last_chunk_remain_ = 0UL;
// holds non chunk-data parts.
// "CRLF chunk-size [chunk-extension] CRLF" or
// "CRLF last-chunk trailer CRLF".
std::string non_chunk_data_;
// If it got all chunked-body, i.e. it sees "last-chunk trailer CRLF",
// it sets done_ to true. In other words, if done_ is false, need more
// data.
bool done_ = false;
std::string error_message_;
};
} // namespace devtools_goma
#endif // DEVTOOLS_GOMA_CLIENT_HTTP_UTIL_H_