grpc-web/net/grpc/gateway/nginx/grpc_gateway_module.c

164 lines
6.5 KiB
C

// The Nginx module for GRPC gateway.
// It proxies the HTTP requests (follows go/http-api) to GRPC backends.
// Usage:
// location / {
// grpc_pass <host>:<port>
// grpc_channel_reuse on|off
// grpc_client_liveness_detection_interval <ms>
// }
// Example:
// location / {
// grpc_pass localhost:8090
// grpc_channel_reuse on
// grpc_client_liveness_detection_interval 60000
// }
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "net/grpc/gateway/frontend/nginx_bridge.h"
#include "third_party/grpc/include/grpc/byte_buffer.h"
#include "third_party/grpc/include/grpc/byte_buffer_reader.h"
#include "third_party/grpc/include/grpc/grpc.h"
#include "third_party/grpc/include/grpc/slice.h"
#include "third_party/grpc/include/grpc/status.h"
#include "third_party/grpc/include/grpc/support/thd.h"
#include "third_party/grpc/include/grpc/support/time.h"
// Tag for requests to GRPC backend. It contains the content and will be send
// back to the grpc_event_callback once the GRPC event comes from the completion
// queue.
typedef struct grpc_event_tag grpc_event_tag;
struct grpc_event_tag {
ngx_http_request_t *ngx_http_request;
grpc_metadata_array recv_init_metadata;
grpc_byte_buffer *recv_message;
grpc_status_code recv_status;
char *recv_status_details;
size_t recv_status_details_capacity;
grpc_metadata_array recv_trailing_metadata;
void (*grpc_event_callback)(grpc_event_tag *, bool);
};
extern ngx_int_t grpc_gateway_init_process(ngx_cycle_t *cycle);
extern void grpc_gateway_exit_process(ngx_cycle_t *cycle);
// Initiates the ngx_grpc_gateway module.
static char *grpc_gateway(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
// Callback when receiving a new HTTP request.
extern ngx_int_t grpc_gateway_handler(ngx_http_request_t *r);
// Creates the local configure.
static void *grpc_gateway_create_loc_conf(ngx_conf_t *cf);
// Merges the local configure.
static char *grpc_gateway_merge_loc_conf(ngx_conf_t *cf, void *parent,
void *child);
// Commands for grpc_gateway module.
static ngx_command_t grpc_gateway_commands[] = {
{ngx_string("grpc_pass"), NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1, grpc_gateway,
NGX_HTTP_LOC_CONF_OFFSET, 0, NULL},
{ngx_string("grpc_channel_reuse"), NGX_HTTP_LOC_CONF | NGX_CONF_FLAG,
ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_grpc_gateway_loc_conf_t, grpc_channel_reuse), NULL},
{ngx_string("grpc_client_liveness_detection_interval"),
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1, ngx_conf_set_msec_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_grpc_gateway_loc_conf_t,
grpc_client_liveness_detection_interval),
NULL},
{ngx_string("grpc_ssl"), NGX_HTTP_LOC_CONF | NGX_CONF_FLAG,
ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_grpc_gateway_loc_conf_t, grpc_ssl), NULL},
{ngx_string("grpc_ssl_target_name_override"),
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1, grpc_gateway, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_grpc_gateway_loc_conf_t, grpc_ssl_target_name_override),
NULL},
{ngx_string("grpc_ssl_pem_root_certs"), NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
grpc_gateway, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_grpc_gateway_loc_conf_t, grpc_ssl_pem_root_certs), NULL},
{ngx_string("grpc_ssl_pem_private_key"), NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
grpc_gateway, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_grpc_gateway_loc_conf_t, grpc_ssl_pem_private_key), NULL},
{ngx_string("grpc_ssl_pem_cert_chain"), NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
grpc_gateway, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_grpc_gateway_loc_conf_t, grpc_ssl_pem_cert_chain), NULL},
ngx_null_command};
// Module context for grpc_gateway module.
static ngx_http_module_t grpc_gateway_module_ctx = {
NULL, /* pre-configuration */
NULL, /* post-configuration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
grpc_gateway_create_loc_conf, /* create location configuration */
grpc_gateway_merge_loc_conf /* merge location configuration */
};
// Nginx module definition for grpc_gateway module.
ngx_module_t grpc_gateway_module = {
NGX_MODULE_V1,
&grpc_gateway_module_ctx, /* module context */
grpc_gateway_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
grpc_gateway_init_process, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
grpc_gateway_exit_process, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING};
char *grpc_gateway(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
ngx_conf_set_str_slot(cf, cmd, conf);
ngx_http_core_loc_conf_t *clcf =
ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = grpc_gateway_handler;
return NGX_CONF_OK;
}
void *grpc_gateway_create_loc_conf(ngx_conf_t *cf) {
ngx_grpc_gateway_loc_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_grpc_gateway_loc_conf_t));
if (conf == NULL) {
return NGX_CONF_ERROR;
}
conf->grpc_channel_reuse = NGX_CONF_UNSET;
conf->grpc_client_liveness_detection_interval = NGX_CONF_UNSET_MSEC;
conf->grpc_ssl = NGX_CONF_UNSET;
return conf;
}
char *grpc_gateway_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) {
ngx_grpc_gateway_loc_conf_t *conf = child;
ngx_grpc_gateway_loc_conf_t *p = parent;
ngx_conf_merge_msec_value(conf->grpc_client_liveness_detection_interval,
p->grpc_client_liveness_detection_interval, 0);
ngx_conf_merge_value(conf->grpc_channel_reuse, p->grpc_channel_reuse, 1);
ngx_conf_merge_str_value(conf->grpc_pass, p->grpc_pass, "");
ngx_conf_merge_value(conf->grpc_ssl, p->grpc_ssl, 0);
ngx_conf_merge_str_value(conf->grpc_ssl_target_name_override,
p->grpc_ssl_target_name_override, "");
ngx_conf_merge_str_value(conf->grpc_ssl_pem_root_certs,
p->grpc_ssl_pem_root_certs, "");
ngx_conf_merge_str_value(conf->grpc_ssl_pem_private_key,
p->grpc_ssl_pem_private_key, "");
ngx_conf_merge_str_value(conf->grpc_ssl_pem_cert_chain,
p->grpc_ssl_pem_cert_chain, "");
return NGX_CONF_OK;
}