1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18
19#ifndef BRPC_HTTP_HEADER_H
20#define BRPC_HTTP_HEADER_H
21
22#include "butil/strings/string_piece.h" // StringPiece
23#include "butil/containers/case_ignored_flat_map.h"
24#include "brpc/uri.h" // URI
25#include "brpc/http_method.h" // HttpMethod
26#include "brpc/http_status_code.h"
27#include "brpc/http2.h"
28
29// To rpc developers: DON'T put impl. details here, use opaque pointers instead.
30
31
32namespace brpc {
33class InputMessageBase;
34namespace policy {
35void ProcessHttpRequest(InputMessageBase *msg);
36class H2StreamContext;
37}
38
39// Non-body part of a HTTP message.
40class HttpHeader {
41public:
42 typedef butil::CaseIgnoredFlatMap<std::string> HeaderMap;
43 typedef HeaderMap::const_iterator HeaderIterator;
44
45 HttpHeader();
46
47 // Exchange internal fields with another HttpHeader.
48 void Swap(HttpHeader &rhs);
49
50 // Reset internal fields as if they're just default-constructed.
51 void Clear();
52
53 // Get http version, 1.1 by default.
54 int major_version() const { return _version.first; }
55 int minor_version() const { return _version.second; }
56 // Change the http version
57 void set_version(int http_major, int http_minor)
58 { _version = std::make_pair(http_major, http_minor); }
59
60 // True if version of http is earlier than 1.1
61 bool before_http_1_1() const
62 { return (major_version() * 10000 + minor_version()) <= 10000; }
63
64 // True if the message is from HTTP2.
65 bool is_http2() const { return major_version() == 2; }
66
67 // Get/set "Content-Type". Notice that you can't get "Content-Type"
68 // via GetHeader().
69 // possible values: "text/plain", "application/json" ...
70 const std::string& content_type() const { return _content_type; }
71 void set_content_type(const std::string& type) { _content_type = type; }
72 void set_content_type(const char* type) { _content_type = type; }
73 std::string& mutable_content_type() { return _content_type; }
74
75 // Get value of a header which is case-insensitive according to:
76 // https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
77 // Namely, GetHeader("log-id"), GetHeader("Log-Id"), GetHeader("LOG-ID")
78 // point to the same value.
79 // Return pointer to the value, NULL on not found.
80 // NOTE: Not work for "Content-Type", call content_type() instead.
81 const std::string* GetHeader(const char* key) const
82 { return _headers.seek(key); }
83 const std::string* GetHeader(const std::string& key) const
84 { return _headers.seek(key); }
85
86 // Set value of a header.
87 // NOTE: Not work for "Content-Type", call set_content_type() instead.
88 void SetHeader(const std::string& key, const std::string& value)
89 { GetOrAddHeader(key) = value; }
90
91 // Remove a header.
92 void RemoveHeader(const char* key) { _headers.erase(key); }
93 void RemoveHeader(const std::string& key) { _headers.erase(key); }
94
95 // Append value to a header. If the header already exists, separate
96 // old value and new value with comma(,) according to:
97 // https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
98 void AppendHeader(const std::string& key, const butil::StringPiece& value);
99
100 // Get header iterators which are invalidated after calling AppendHeader()
101 HeaderIterator HeaderBegin() const { return _headers.begin(); }
102 HeaderIterator HeaderEnd() const { return _headers.end(); }
103 // #headers
104 size_t HeaderCount() const { return _headers.size(); }
105
106 // Get the URI object, check src/brpc/uri.h for details.
107 const URI& uri() const { return _uri; }
108 URI& uri() { return _uri; }
109
110 // Get/set http method.
111 HttpMethod method() const { return _method; }
112 void set_method(const HttpMethod method) { _method = method; }
113
114 // Get/set status-code and reason-phrase. Notice that the const char*
115 // returned by reason_phrase() will be invalidated after next call to
116 // set_status_code().
117 int status_code() const { return _status_code; }
118 const char* reason_phrase() const;
119 void set_status_code(int status_code);
120
121 // The URL path removed with matched prefix.
122 // NOTE: always normalized and NOT started with /.
123 //
124 // Accessing HttpService.Echo
125 // [URL] [unresolved_path]
126 // "/HttpService/Echo" ""
127 // "/HttpService/Echo/Foo" "Foo"
128 // "/HttpService/Echo/Foo/Bar" "Foo/Bar"
129 // "/HttpService//Echo///Foo//" "Foo"
130 //
131 // Accessing FileService.default_method:
132 // [URL] [unresolved_path]
133 // "/FileService" ""
134 // "/FileService/123.txt" "123.txt"
135 // "/FileService/mydir/123.txt" "mydir/123.txt"
136 // "/FileService//mydir///123.txt//" "mydir/123.txt"
137 const std::string& unresolved_path() const { return _unresolved_path; }
138
139private:
140friend class HttpMessage;
141friend class HttpMessageSerializer;
142friend class policy::H2StreamContext;
143friend void policy::ProcessHttpRequest(InputMessageBase *msg);
144
145 std::string& GetOrAddHeader(const std::string& key) {
146 if (!_headers.initialized()) {
147 _headers.init(29);
148 }
149 return _headers[key];
150 }
151
152 HeaderMap _headers;
153 URI _uri;
154 int _status_code;
155 HttpMethod _method;
156 std::string _content_type;
157 std::string _unresolved_path;
158 std::pair<int, int> _version;
159};
160
161const HttpHeader& DefaultHttpHeader();
162
163} // namespace brpc
164
165
166#endif //BRPC_HTTP_HEADER_H
167