int mg_vcasecmp(const struct mg_str *str1, const char *str2) { size_t n2 = strlen(str2), n1 = str1->len; int r = mg_ncasecmp(str1->p, str2, (n1 < n2) ? n1 : n2); if (r == 0) { return n1 - n2; } return r; }
static void forward(struct conn_data *conn, struct http_message *hm, struct peer *src_peer, struct peer *dst_peer) { struct mg_connection *src = src_peer->nc; struct mg_connection *dst = dst_peer->nc; struct mbuf *io = &src->recv_mbuf; int i; int is_request = (src_peer == &conn->client); src_peer->body_len = hm->body.len; struct http_backend *be = conn->be_conn->be; if (is_request) { /* Write rewritten request line. */ size_t trim_len = strlen(be->uri_prefix); mg_printf(dst, "%.*s%s%.*s\r\n", (int) (hm->uri.p - io->buf), io->buf, be->uri_prefix_replacement, (int) (hm->proto.p + hm->proto.len - (hm->uri.p + trim_len)), hm->uri.p + trim_len); } else { /* Reply line goes without modification */ mg_printf(dst, "%.*s %d %.*s\r\n", (int) hm->proto.len, hm->proto.p, (int) hm->resp_code, (int) hm->resp_status_msg.len, hm->resp_status_msg.p); } /* Headers. */ for (i = 0; i < MG_MAX_HTTP_HEADERS && hm->header_names[i].len > 0; i++) { struct mg_str hn = hm->header_names[i]; struct mg_str hv = hm->header_values[i]; #if MG_ENABLE_SSL /* * If we terminate SSL and backend redirects to local HTTP port, * strip protocol to let client use HTTPS. * TODO(lsm): web page content may also contain local HTTP references, * they need to be rewritten too. */ if (mg_vcasecmp(&hn, "Location") == 0 && s_ssl_cert != NULL) { size_t hlen = strlen(be->host_port); const char *hp = be->host_port, *p = memchr(hp, ':', hlen); if (p == NULL) { p = hp + hlen; } if (mg_ncasecmp(hv.p, "http://", 7) == 0 && mg_ncasecmp(hv.p + 7, hp, (p - hp)) == 0) { mg_printf(dst, "Location: %.*s\r\n", (int) (hv.len - (7 + (p - hp))), hv.p + 7 + (p - hp)); continue; } } #endif /* We always rewrite the connection header depending on the settings. */ if (mg_vcasecmp(&hn, "Connection") == 0) continue; /* Don't pass chunked transfer encoding to the client */ if (mg_vcasecmp(&hn, "Transfer-encoding") == 0 && mg_vcasecmp(&hv, "chunked") == 0) { continue; } mg_printf(dst, "%.*s: %.*s\r\n", (int) hn.len, hn.p, (int) hv.len, hv.p); } /* Emit the connection header. */ const char *connection_mode = "close"; if (dst_peer == &conn->backend) { if (s_backend_keepalive) connection_mode = "keep-alive"; } else { if (conn->client.flags.keep_alive) connection_mode = "keep-alive"; } mg_printf(dst, "Connection: %s\r\n", connection_mode); mg_printf(dst, "%s", "\r\n"); mbuf_remove(io, hm->body.p - hm->message.p); /* We've forwarded headers */ dst_peer->flags.headers_sent = 1; forward_body(src_peer, dst_peer); }