forked from DalavanCloud/grpc-web
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnginx_http_frontend.h
166 lines (130 loc) · 5.47 KB
/
nginx_http_frontend.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/**
*
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef NET_GRPC_GATEWAY_FRONTEND_NGINX_HTTP_FRONTEND_H_
#define NET_GRPC_GATEWAY_FRONTEND_NGINX_HTTP_FRONTEND_H_
// NOTE: Required on top in order to include ngx_config.h libc defines
#include "net/grpc/gateway/nginx_includes.h"
#include <algorithm>
#include <functional>
#include <map>
#include <memory>
#include "net/grpc/gateway/backend/backend.h"
#include "net/grpc/gateway/codec/decoder.h"
#include "net/grpc/gateway/codec/encoder.h"
#include "net/grpc/gateway/frontend/frontend.h"
#include "net/grpc/gateway/runtime/constants.h"
#include "third_party/grpc/include/grpcpp/support/byte_buffer.h"
#include "third_party/grpc/include/grpcpp/support/string_ref.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
// The pointer of the frontend instance which serves the request.
std::shared_ptr<grpc::gateway::Frontend> frontend;
} grpc_gateway_request_context;
// Interface between nginx and GRPC gateway. Starts with "grpc_gateway_" prefix.
ngx_int_t grpc_gateway_handler(ngx_http_request_t *r);
ngx_int_t grpc_gateway_init_process(ngx_cycle_t *cycle);
void grpc_gateway_exit_process(ngx_cycle_t *cycle);
// Internal methods for nginx bridge.
void continue_read_request_body(ngx_http_request_t *r);
grpc::gateway::Frontend *get_frontend(ngx_http_request_t *r);
// Client liveness detection event handler.
void client_liveness_detection_handler(ngx_event_t *event);
#ifdef __cplusplus
}
#endif
namespace grpc {
namespace gateway {
// The HTTP proxy based on Nginx.
class NginxHttpFrontend : public Frontend {
public:
explicit NginxHttpFrontend(std::unique_ptr<Backend> backend);
~NginxHttpFrontend() override;
NginxHttpFrontend(const NginxHttpFrontend &) = delete;
NginxHttpFrontend &operator=(const NginxHttpFrontend &) = delete;
void Start() override;
void Send(std::unique_ptr<Response> response) override;
void set_http_request(ngx_http_request_t *http_request) {
http_request_ = http_request;
}
void set_encoder(std::unique_ptr<Encoder> encoder) {
encoder_ = std::move(encoder);
}
void set_decoder(std::unique_ptr<Decoder> decoder) {
decoder_ = std::move(decoder);
}
void set_request_protocol(Protocol protocol) { request_protocol_ = protocol; }
void set_response_protocol(Protocol protocol) {
response_protocol_ = protocol;
}
void set_client_liveness_detection_interval(
ngx_msec_t client_liveness_detection_interval) {
client_liveness_detection_interval_ = client_liveness_detection_interval;
}
void OnClientLivenessDetectionEvent(ngx_event_t *event);
void StopClientLivenessDetection();
private:
friend void ::continue_read_request_body(ngx_http_request_t *r);
// Invoked by nginx when more request body is available to read.
void ContinueReadRequestBody();
// Decode and send GRPC messages to backend. Returns true if a GRPC message
// has been sent.
bool SendRequestToBackend();
// Add request initial metadata to the request to backend. It's no-op if
// request initial metadata has been sent before.
void AddRequestInitialMetadataOnce(const std::unique_ptr<Request> &request);
// Add a request message to the request to backend.
void AddRequestMessage(const std::unique_ptr<Request> &request);
// Decode the request body.
Status DecodeRequestBody();
// Callback when the GRPC message has been sent to backend.
void SendRequestToBackendDone(bool result);
void SendResponseMessageToClient(Response *response);
void SendResponseStatusToClient(Response *response);
void SendResponseHeadersToClient(Response *response);
void SendResponseTrailersToClient(Response *response);
void SendErrorToClient(const grpc::Status &status);
void WriteToNginxResponse(uint8_t *data, size_t size);
ngx_http_request_t *http_request_;
std::unique_ptr<Decoder> decoder_;
std::unique_ptr<Encoder> encoder_;
// The frontend protocol of the current processing request.
Protocol request_protocol_;
// The frontend protocol of the current processing response.
Protocol response_protocol_;
// True if already reach the end of the HTTP request from nginx.
bool is_request_half_closed_;
// True if the half close has been sent to the GRPC backend.
bool is_request_half_closed_sent_;
// True if the request metadata has been sent to the GRPC backend.
bool is_request_init_metadata_sent_;
// True if the response headers have been sent back via nginx.
bool is_response_http_headers_sent_;
// True if the response trailers have been sent back via nginx.
bool is_response_status_sent_;
// A timer for client liveness detection.
ngx_event_t *client_liveness_detection_timer_;
// The client liveness detection interval in millisecond.
ngx_msec_t client_liveness_detection_interval_;
// A dummy connection wraps the client liveness detection timer.
ngx_connection_t *client_liveness_detection_timer_connection_;
};
} // namespace gateway
} // namespace grpc
#endif // NET_GRPC_GATEWAY_FRONTEND_NGINX_HTTP_FRONTEND_H_