Imported Upstream version 1.0.0
[platform/upstream/nghttp2.git] / src / shrpx_https_upstream.cc
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2012 Tatsuhiro Tsujikawa
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #include "shrpx_https_upstream.h"
26
27 #include <cassert>
28 #include <set>
29 #include <sstream>
30
31 #include "shrpx_client_handler.h"
32 #include "shrpx_downstream.h"
33 #include "shrpx_downstream_connection.h"
34 #include "shrpx_http.h"
35 #include "shrpx_config.h"
36 #include "shrpx_error.h"
37 #include "shrpx_log_config.h"
38 #include "shrpx_worker.h"
39 #include "http2.h"
40 #include "util.h"
41 #include "template.h"
42
43 using namespace nghttp2;
44
45 namespace shrpx {
46
47 HttpsUpstream::HttpsUpstream(ClientHandler *handler)
48     : handler_(handler), current_header_length_(0),
49       ioctrl_(handler->get_rlimit()) {
50   http_parser_init(&htp_, HTTP_REQUEST);
51   htp_.data = this;
52 }
53
54 HttpsUpstream::~HttpsUpstream() {}
55
56 void HttpsUpstream::reset_current_header_length() {
57   current_header_length_ = 0;
58 }
59
60 namespace {
61 int htp_msg_begin(http_parser *htp) {
62   auto upstream = static_cast<HttpsUpstream *>(htp->data);
63   if (LOG_ENABLED(INFO)) {
64     ULOG(INFO, upstream) << "HTTP request started";
65   }
66   upstream->reset_current_header_length();
67
68   auto handler = upstream->get_client_handler();
69
70   // TODO specify 0 as priority for now
71   upstream->attach_downstream(
72       make_unique<Downstream>(upstream, handler->get_mcpool(), 0, 0));
73   return 0;
74 }
75 } // namespace
76
77 namespace {
78 int htp_uricb(http_parser *htp, const char *data, size_t len) {
79   auto upstream = static_cast<HttpsUpstream *>(htp->data);
80   auto downstream = upstream->get_downstream();
81   if (downstream->get_request_headers_sum() + len >
82       get_config()->header_field_buffer) {
83     if (LOG_ENABLED(INFO)) {
84       ULOG(INFO, upstream) << "Too large URI size="
85                            << downstream->get_request_headers_sum() + len;
86     }
87     assert(downstream->get_request_state() == Downstream::INITIAL);
88     downstream->set_request_state(Downstream::HTTP1_REQUEST_HEADER_TOO_LARGE);
89     return -1;
90   }
91   downstream->add_request_headers_sum(len);
92   downstream->append_request_path(data, len);
93   return 0;
94 }
95 } // namespace
96
97 namespace {
98 int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
99   auto upstream = static_cast<HttpsUpstream *>(htp->data);
100   auto downstream = upstream->get_downstream();
101   if (downstream->get_request_headers_sum() + len >
102       get_config()->header_field_buffer) {
103     if (LOG_ENABLED(INFO)) {
104       ULOG(INFO, upstream) << "Too large header block size="
105                            << downstream->get_request_headers_sum() + len;
106     }
107     if (downstream->get_request_state() == Downstream::INITIAL) {
108       downstream->set_request_state(Downstream::HTTP1_REQUEST_HEADER_TOO_LARGE);
109     }
110     return -1;
111   }
112   if (downstream->get_request_state() == Downstream::INITIAL) {
113     if (downstream->get_request_header_key_prev()) {
114       downstream->append_last_request_header_key(data, len);
115     } else {
116       if (downstream->get_request_headers().size() >=
117           get_config()->max_header_fields) {
118         if (LOG_ENABLED(INFO)) {
119           ULOG(INFO, upstream) << "Too many header field num="
120                                << downstream->get_request_headers().size() + 1;
121         }
122         downstream->set_request_state(
123             Downstream::HTTP1_REQUEST_HEADER_TOO_LARGE);
124         return -1;
125       }
126       downstream->add_request_header(std::string(data, len), "");
127     }
128   } else {
129     // trailer part
130     if (downstream->get_request_trailer_key_prev()) {
131       downstream->append_last_request_trailer_key(data, len);
132     } else {
133       if (downstream->get_request_headers().size() >=
134           get_config()->max_header_fields) {
135         if (LOG_ENABLED(INFO)) {
136           ULOG(INFO, upstream) << "Too many header field num="
137                                << downstream->get_request_headers().size() + 1;
138         }
139         return -1;
140       }
141       downstream->add_request_trailer(std::string(data, len), "");
142     }
143   }
144   return 0;
145 }
146 } // namespace
147
148 namespace {
149 int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) {
150   auto upstream = static_cast<HttpsUpstream *>(htp->data);
151   auto downstream = upstream->get_downstream();
152   if (downstream->get_request_headers_sum() + len >
153       get_config()->header_field_buffer) {
154     if (LOG_ENABLED(INFO)) {
155       ULOG(INFO, upstream) << "Too large header block size="
156                            << downstream->get_request_headers_sum() + len;
157     }
158     if (downstream->get_request_state() == Downstream::INITIAL) {
159       downstream->set_request_state(Downstream::HTTP1_REQUEST_HEADER_TOO_LARGE);
160     }
161     return -1;
162   }
163   if (downstream->get_request_state() == Downstream::INITIAL) {
164     if (downstream->get_request_header_key_prev()) {
165       downstream->set_last_request_header_value(data, len);
166     } else {
167       downstream->append_last_request_header_value(data, len);
168     }
169   } else {
170     if (downstream->get_request_trailer_key_prev()) {
171       downstream->set_last_request_trailer_value(data, len);
172     } else {
173       downstream->append_last_request_trailer_value(data, len);
174     }
175   }
176   return 0;
177 }
178 } // namespace
179
180 namespace {
181 void rewrite_request_host_path_from_uri(Downstream *downstream, const char *uri,
182                                         http_parser_url &u) {
183   assert(u.field_set & (1 << UF_HOST));
184
185   // As per https://tools.ietf.org/html/rfc7230#section-5.4, we
186   // rewrite host header field with authority component.
187   std::string authority;
188   http2::copy_url_component(authority, &u, UF_HOST, uri);
189   // TODO properly check IPv6 numeric address
190   if (authority.find(':') != std::string::npos) {
191     authority = '[' + authority;
192     authority += ']';
193   }
194   if (u.field_set & (1 << UF_PORT)) {
195     authority += ':';
196     authority += util::utos(u.port);
197   }
198   downstream->set_request_http2_authority(authority);
199
200   std::string path;
201   if (u.field_set & (1 << UF_PATH)) {
202     http2::copy_url_component(path, &u, UF_PATH, uri);
203   } else if (downstream->get_request_method() == "OPTIONS") {
204     // Server-wide OPTIONS takes following form in proxy request:
205     //
206     // OPTIONS http://example.org HTTP/1.1
207     //
208     // Notice that no slash after authority. See
209     // http://tools.ietf.org/html/rfc7230#section-5.3.4
210     downstream->set_request_path("*");
211     // we ignore query component here
212     return;
213   } else {
214     path = "/";
215   }
216   if (u.field_set & (1 << UF_QUERY)) {
217     auto &fdata = u.field_data[UF_QUERY];
218     path += '?';
219     path.append(uri + fdata.off, fdata.len);
220   }
221   downstream->set_request_path(std::move(path));
222   if (get_config()->http2_proxy || get_config()->client_proxy) {
223     std::string scheme;
224     http2::copy_url_component(scheme, &u, UF_SCHEMA, uri);
225     downstream->set_request_http2_scheme(std::move(scheme));
226   }
227 }
228 } // namespace
229
230 namespace {
231 int htp_hdrs_completecb(http_parser *htp) {
232   int rv;
233   auto upstream = static_cast<HttpsUpstream *>(htp->data);
234   if (LOG_ENABLED(INFO)) {
235     ULOG(INFO, upstream) << "HTTP request headers completed";
236   }
237   auto downstream = upstream->get_downstream();
238
239   downstream->set_request_method(
240       http_method_str((enum http_method)htp->method));
241   downstream->set_request_major(htp->http_major);
242   downstream->set_request_minor(htp->http_minor);
243
244   downstream->set_request_connection_close(!http_should_keep_alive(htp));
245
246   if (LOG_ENABLED(INFO)) {
247     std::stringstream ss;
248     ss << downstream->get_request_method() << " "
249        << downstream->get_request_path() << " "
250        << "HTTP/" << downstream->get_request_major() << "."
251        << downstream->get_request_minor() << "\n";
252     const auto &headers = downstream->get_request_headers();
253     for (size_t i = 0; i < headers.size(); ++i) {
254       ss << TTY_HTTP_HD << headers[i].name << TTY_RST << ": "
255          << headers[i].value << "\n";
256     }
257     ULOG(INFO, upstream) << "HTTP request headers\n" << ss.str();
258   }
259
260   if (downstream->index_request_headers() != 0) {
261     return -1;
262   }
263
264   if (downstream->get_request_major() == 1 &&
265       downstream->get_request_minor() == 1 &&
266       !downstream->get_request_header(http2::HD_HOST)) {
267     return -1;
268   }
269
270   downstream->inspect_http1_request();
271
272   if (downstream->get_request_method() != "CONNECT") {
273     http_parser_url u{};
274     // make a copy of request path, since we may set request path
275     // while we are refering to original request path.
276     auto uri = downstream->get_request_path();
277     rv = http_parser_parse_url(uri.c_str(),
278                                downstream->get_request_path().size(), 0, &u);
279     if (rv != 0) {
280       // Expect to respond with 400 bad request
281       return -1;
282     }
283     // checking UF_HOST could be redundant, but just in case ...
284     if (!(u.field_set & (1 << UF_SCHEMA)) || !(u.field_set & (1 << UF_HOST))) {
285       if (get_config()->http2_proxy || get_config()->client_proxy) {
286         // Request URI should be absolute-form for client proxy mode
287         return -1;
288       }
289     } else {
290       rewrite_request_host_path_from_uri(downstream, uri.c_str(), u);
291     }
292   }
293
294   rv = downstream->attach_downstream_connection(
295       upstream->get_client_handler()->get_downstream_connection());
296
297   if (rv != 0) {
298     downstream->set_request_state(Downstream::CONNECT_FAIL);
299
300     return -1;
301   }
302
303   rv = downstream->push_request_headers();
304
305   if (rv != 0) {
306     return -1;
307   }
308
309   downstream->set_request_state(Downstream::HEADER_COMPLETE);
310
311   return 0;
312 }
313 } // namespace
314
315 namespace {
316 int htp_bodycb(http_parser *htp, const char *data, size_t len) {
317   int rv;
318   auto upstream = static_cast<HttpsUpstream *>(htp->data);
319   auto downstream = upstream->get_downstream();
320   rv = downstream->push_upload_data_chunk(
321       reinterpret_cast<const uint8_t *>(data), len);
322   if (rv != 0) {
323     return -1;
324   }
325   return 0;
326 }
327 } // namespace
328
329 namespace {
330 int htp_msg_completecb(http_parser *htp) {
331   int rv;
332   auto upstream = static_cast<HttpsUpstream *>(htp->data);
333   if (LOG_ENABLED(INFO)) {
334     ULOG(INFO, upstream) << "HTTP request completed";
335   }
336   auto handler = upstream->get_client_handler();
337   auto downstream = upstream->get_downstream();
338   downstream->set_request_state(Downstream::MSG_COMPLETE);
339   rv = downstream->end_upload_data();
340   if (rv != 0) {
341     return -1;
342   }
343
344   if (handler->get_http2_upgrade_allowed() &&
345       downstream->get_http2_upgrade_request() &&
346       handler->perform_http2_upgrade(upstream) != 0) {
347     if (LOG_ENABLED(INFO)) {
348       ULOG(INFO, upstream) << "HTTP Upgrade to HTTP/2 failed";
349     }
350   }
351
352   // Stop further processing to complete this request
353   http_parser_pause(htp, 1);
354   return 0;
355 }
356 } // namespace
357
358 namespace {
359 http_parser_settings htp_hooks = {
360     htp_msg_begin,       // http_cb      on_message_begin;
361     htp_uricb,           // http_data_cb on_url;
362     nullptr,             // http_data_cb on_status;
363     htp_hdr_keycb,       // http_data_cb on_header_field;
364     htp_hdr_valcb,       // http_data_cb on_header_value;
365     htp_hdrs_completecb, // http_cb      on_headers_complete;
366     htp_bodycb,          // http_data_cb on_body;
367     htp_msg_completecb   // http_cb      on_message_complete;
368 };
369 } // namespace
370
371 // on_read() does not consume all available data in input buffer if
372 // one http request is fully received.
373 int HttpsUpstream::on_read() {
374   auto rb = handler_->get_rb();
375   auto rlimit = handler_->get_rlimit();
376   auto downstream = get_downstream();
377
378   if (rb->rleft() == 0) {
379     return 0;
380   }
381
382   // downstream can be nullptr here, because it is initialized in the
383   // callback chain called by http_parser_execute()
384   if (downstream && downstream->get_upgraded()) {
385
386     auto rv = downstream->push_upload_data_chunk(rb->pos, rb->rleft());
387
388     if (rv != 0) {
389       return -1;
390     }
391
392     rb->reset();
393     rlimit->startw();
394
395     if (downstream->request_buf_full()) {
396       if (LOG_ENABLED(INFO)) {
397         ULOG(INFO, this) << "Downstream request buf is full";
398       }
399       pause_read(SHRPX_NO_BUFFER);
400
401       return 0;
402     }
403
404     return 0;
405   }
406
407   if (downstream) {
408     // To avoid reading next pipelined request
409     switch (downstream->get_request_state()) {
410     case Downstream::INITIAL:
411     case Downstream::HEADER_COMPLETE:
412       break;
413     default:
414       return 0;
415     }
416   }
417
418   // http_parser_execute() does nothing once it entered error state.
419   auto nread = http_parser_execute(
420       &htp_, &htp_hooks, reinterpret_cast<const char *>(rb->pos), rb->rleft());
421
422   rb->drain(nread);
423   rlimit->startw();
424
425   // Well, actually header length + some body bytes
426   current_header_length_ += nread;
427
428   // Get downstream again because it may be initialized in http parser
429   // execution
430   downstream = get_downstream();
431
432   auto htperr = HTTP_PARSER_ERRNO(&htp_);
433
434   if (htperr == HPE_PAUSED) {
435     return 0;
436   }
437
438   if (htperr != HPE_OK) {
439     if (LOG_ENABLED(INFO)) {
440       ULOG(INFO, this) << "HTTP parse failure: "
441                        << "(" << http_errno_name(htperr) << ") "
442                        << http_errno_description(htperr);
443     }
444
445     if (downstream && downstream->get_response_state() != Downstream::INITIAL) {
446       handler_->set_should_close_after_write(true);
447       handler_->signal_write();
448       return 0;
449     }
450
451     unsigned int status_code;
452
453     if (downstream) {
454       if (downstream->get_request_state() == Downstream::CONNECT_FAIL) {
455         status_code = 503;
456       } else if (downstream->get_request_state() ==
457                  Downstream::HTTP1_REQUEST_HEADER_TOO_LARGE) {
458         status_code = 431;
459       } else {
460         status_code = 400;
461       }
462     } else {
463       status_code = 400;
464     }
465
466     error_reply(status_code);
467
468     handler_->signal_write();
469
470     return 0;
471   }
472
473   // downstream can be NULL here.
474   if (downstream && downstream->request_buf_full()) {
475     if (LOG_ENABLED(INFO)) {
476       ULOG(INFO, this) << "Downstream request buffer is full";
477     }
478
479     pause_read(SHRPX_NO_BUFFER);
480
481     return 0;
482   }
483
484   return 0;
485 }
486
487 int HttpsUpstream::on_write() {
488   auto downstream = get_downstream();
489   if (!downstream) {
490     return 0;
491   }
492   auto wb = handler_->get_wb();
493   if (wb->wleft() == 0) {
494     return 0;
495   }
496
497   auto dconn = downstream->get_downstream_connection();
498   auto output = downstream->get_response_buf();
499
500   if (output->rleft() == 0 && dconn &&
501       downstream->get_response_state() != Downstream::MSG_COMPLETE) {
502     if (downstream->resume_read(SHRPX_NO_BUFFER,
503                                 downstream->get_response_datalen()) != 0) {
504       return -1;
505     }
506
507     if (downstream_read(dconn) != 0) {
508       return -1;
509     }
510   }
511
512   auto n = output->remove(wb->last, wb->wleft());
513   wb->write(n);
514
515   if (wb->rleft() > 0) {
516     return 0;
517   }
518
519   // We need to postpone detachment until all data are sent so that
520   // we can notify nghttp2 library all data consumed.
521   if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
522     if (downstream->get_response_connection_close()) {
523       // Connection close
524       downstream->pop_downstream_connection();
525       // dconn was deleted
526     } else {
527       // Keep-alive
528       downstream->detach_downstream_connection();
529     }
530     // We need this if response ends before request.
531     if (downstream->get_request_state() == Downstream::MSG_COMPLETE) {
532       delete_downstream();
533       return resume_read(SHRPX_NO_BUFFER, nullptr, 0);
534     }
535   }
536
537   return downstream->resume_read(SHRPX_NO_BUFFER,
538                                  downstream->get_response_datalen());
539 }
540
541 int HttpsUpstream::on_event() { return 0; }
542
543 ClientHandler *HttpsUpstream::get_client_handler() const { return handler_; }
544
545 void HttpsUpstream::pause_read(IOCtrlReason reason) {
546   ioctrl_.pause_read(reason);
547 }
548
549 int HttpsUpstream::resume_read(IOCtrlReason reason, Downstream *downstream,
550                                size_t consumed) {
551   // downstream could be nullptr
552   if (downstream && downstream->request_buf_full()) {
553     return 0;
554   }
555   if (ioctrl_.resume_read(reason)) {
556     // Process remaining data in input buffer here because these bytes
557     // are not notified by readcb until new data arrive.
558     http_parser_pause(&htp_, 0);
559     return on_read();
560   }
561
562   return 0;
563 }
564
565 int HttpsUpstream::downstream_read(DownstreamConnection *dconn) {
566   auto downstream = dconn->get_downstream();
567   int rv;
568
569   rv = downstream->on_read();
570
571   if (rv == SHRPX_ERR_EOF) {
572     return downstream_eof(dconn);
573   }
574
575   if (rv < 0) {
576     return downstream_error(dconn, Downstream::EVENT_ERROR);
577   }
578
579   if (downstream->get_response_state() == Downstream::MSG_RESET) {
580     return -1;
581   }
582
583   if (downstream->get_response_state() == Downstream::MSG_BAD_HEADER) {
584     error_reply(502);
585     downstream->pop_downstream_connection();
586     goto end;
587   }
588
589   // Detach downstream connection early so that it could be reused
590   // without hitting server's request timeout.
591   if (downstream->get_response_state() == Downstream::MSG_COMPLETE &&
592       !downstream->get_response_connection_close()) {
593     // Keep-alive
594     downstream->detach_downstream_connection();
595   }
596
597 end:
598   handler_->signal_write();
599
600   return 0;
601 }
602
603 int HttpsUpstream::downstream_write(DownstreamConnection *dconn) {
604   int rv;
605   rv = dconn->on_write();
606   if (rv == SHRPX_ERR_NETWORK) {
607     return downstream_error(dconn, Downstream::EVENT_ERROR);
608   }
609
610   if (rv != 0) {
611     return -1;
612   }
613
614   return 0;
615 }
616
617 int HttpsUpstream::downstream_eof(DownstreamConnection *dconn) {
618   auto downstream = dconn->get_downstream();
619
620   if (LOG_ENABLED(INFO)) {
621     DCLOG(INFO, dconn) << "EOF";
622   }
623
624   if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
625     goto end;
626   }
627
628   if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
629     // Server may indicate the end of the request by EOF
630     if (LOG_ENABLED(INFO)) {
631       DCLOG(INFO, dconn) << "The end of the response body was indicated by "
632                          << "EOF";
633     }
634     on_downstream_body_complete(downstream);
635     downstream->set_response_state(Downstream::MSG_COMPLETE);
636     downstream->pop_downstream_connection();
637     goto end;
638   }
639
640   if (downstream->get_response_state() == Downstream::INITIAL) {
641     // we did not send any response headers, so we can reply error
642     // message.
643     if (LOG_ENABLED(INFO)) {
644       DCLOG(INFO, dconn) << "Return error reply";
645     }
646     error_reply(502);
647     downstream->pop_downstream_connection();
648     goto end;
649   }
650
651   // Otherwise, we don't know how to recover from this situation. Just
652   // drop connection.
653   return -1;
654 end:
655   handler_->signal_write();
656
657   return 0;
658 }
659
660 int HttpsUpstream::downstream_error(DownstreamConnection *dconn, int events) {
661   auto downstream = dconn->get_downstream();
662   if (LOG_ENABLED(INFO)) {
663     if (events & Downstream::EVENT_ERROR) {
664       DCLOG(INFO, dconn) << "Network error/general error";
665     } else {
666       DCLOG(INFO, dconn) << "Timeout";
667     }
668   }
669   if (downstream->get_response_state() != Downstream::INITIAL) {
670     return -1;
671   }
672
673   unsigned int status;
674   if (events & Downstream::EVENT_TIMEOUT) {
675     status = 504;
676   } else {
677     status = 502;
678   }
679   error_reply(status);
680
681   downstream->pop_downstream_connection();
682
683   handler_->signal_write();
684   return 0;
685 }
686
687 void HttpsUpstream::error_reply(unsigned int status_code) {
688   auto html = http::create_error_html(status_code);
689   auto downstream = get_downstream();
690
691   if (!downstream) {
692     attach_downstream(
693         make_unique<Downstream>(this, handler_->get_mcpool(), 1, 1));
694     downstream = get_downstream();
695   }
696
697   downstream->set_response_http_status(status_code);
698   // we are going to close connection for both frontend and backend in
699   // error condition.  This is safest option.
700   downstream->set_response_connection_close(true);
701   handler_->set_should_close_after_write(true);
702
703   auto output = downstream->get_response_buf();
704
705   output->append("HTTP/1.1 ");
706   auto status_str = http2::get_status_string(status_code);
707   output->append(status_str.c_str(), status_str.size());
708   output->append("\r\nServer: ");
709   output->append(get_config()->server_name, strlen(get_config()->server_name));
710   output->append("\r\nContent-Length: ");
711   auto cl = util::utos(html.size());
712   output->append(cl.c_str(), cl.size());
713   output->append("\r\nContent-Type: text/html; "
714                  "charset=UTF-8\r\nConnection: close\r\n\r\n");
715   output->append(html.c_str(), html.size());
716
717   downstream->add_response_sent_bodylen(html.size());
718   downstream->set_response_state(Downstream::MSG_COMPLETE);
719 }
720
721 void HttpsUpstream::attach_downstream(std::unique_ptr<Downstream> downstream) {
722   assert(!downstream_);
723   downstream_ = std::move(downstream);
724 }
725
726 void HttpsUpstream::delete_downstream() {
727   if (downstream_ && downstream_->accesslog_ready()) {
728     handler_->write_accesslog(downstream_.get());
729   }
730
731   downstream_.reset();
732 }
733
734 Downstream *HttpsUpstream::get_downstream() const { return downstream_.get(); }
735
736 std::unique_ptr<Downstream> HttpsUpstream::pop_downstream() {
737   return std::unique_ptr<Downstream>(downstream_.release());
738 }
739
740 int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
741   if (LOG_ENABLED(INFO)) {
742     if (downstream->get_non_final_response()) {
743       DLOG(INFO, downstream) << "HTTP non-final response header";
744     } else {
745       DLOG(INFO, downstream) << "HTTP response header completed";
746     }
747   }
748
749   std::string hdrs = "HTTP/";
750   hdrs += util::utos(downstream->get_request_major());
751   hdrs += ".";
752   hdrs += util::utos(downstream->get_request_minor());
753   hdrs += " ";
754   hdrs += http2::get_status_string(downstream->get_response_http_status());
755   hdrs += "\r\n";
756
757   if (!get_config()->http2_proxy && !get_config()->client_proxy &&
758       !get_config()->no_location_rewrite) {
759     downstream->rewrite_location_response_header(
760         get_client_handler()->get_upstream_scheme());
761   }
762
763   http2::build_http1_headers_from_headers(hdrs,
764                                           downstream->get_response_headers());
765
766   auto output = downstream->get_response_buf();
767
768   if (downstream->get_non_final_response()) {
769     hdrs += "\r\n";
770
771     if (LOG_ENABLED(INFO)) {
772       log_response_headers(hdrs);
773     }
774
775     output->append(hdrs.c_str(), hdrs.size());
776
777     downstream->clear_response_headers();
778
779     return 0;
780   }
781
782   auto worker = handler_->get_worker();
783
784   // after graceful shutdown commenced, add connection: close header
785   // field.
786   if (worker->get_graceful_shutdown()) {
787     downstream->set_response_connection_close(true);
788   }
789
790   // We check downstream->get_response_connection_close() in case when
791   // the Content-Length is not available.
792   if (!downstream->get_request_connection_close() &&
793       !downstream->get_response_connection_close()) {
794     if (downstream->get_request_major() <= 0 ||
795         downstream->get_request_minor() <= 0) {
796       // We add this header for HTTP/1.0 or HTTP/0.9 clients
797       hdrs += "Connection: Keep-Alive\r\n";
798     }
799   } else if (!downstream->get_upgraded() ||
800              downstream->get_request_method() != "CONNECT") {
801     hdrs += "Connection: close\r\n";
802   }
803
804   if (!downstream->get_response_header(http2::HD_ALT_SVC)) {
805     // We won't change or alter alt-svc from backend for now
806     if (!get_config()->altsvcs.empty()) {
807       hdrs += "Alt-Svc: ";
808
809       for (auto &altsvc : get_config()->altsvcs) {
810         hdrs += util::percent_encode_token(altsvc.protocol_id);
811         hdrs += "=\"";
812         hdrs += util::quote_string(std::string(altsvc.host, altsvc.host_len));
813         hdrs += ":";
814         hdrs += util::utos(altsvc.port);
815         hdrs += "\", ";
816       }
817
818       hdrs[hdrs.size() - 2] = '\r';
819       hdrs[hdrs.size() - 1] = '\n';
820     }
821   }
822
823   if (!get_config()->http2_proxy && !get_config()->client_proxy) {
824     hdrs += "Server: ";
825     hdrs += get_config()->server_name;
826     hdrs += "\r\n";
827   } else {
828     auto server = downstream->get_response_header(http2::HD_SERVER);
829     if (server) {
830       hdrs += "Server: ";
831       hdrs += (*server).value;
832       hdrs += "\r\n";
833     }
834   }
835
836   auto via = downstream->get_response_header(http2::HD_VIA);
837   if (get_config()->no_via) {
838     if (via) {
839       hdrs += "Via: ";
840       hdrs += (*via).value;
841       hdrs += "\r\n";
842     }
843   } else {
844     hdrs += "Via: ";
845     if (via) {
846       hdrs += (*via).value;
847       hdrs += ", ";
848     }
849     hdrs += http::create_via_header_value(downstream->get_response_major(),
850                                           downstream->get_response_minor());
851     hdrs += "\r\n";
852   }
853
854   for (auto &p : get_config()->add_response_headers) {
855     hdrs += p.first;
856     hdrs += ": ";
857     hdrs += p.second;
858     hdrs += "\r\n";
859   }
860
861   hdrs += "\r\n";
862
863   if (LOG_ENABLED(INFO)) {
864     log_response_headers(hdrs);
865   }
866
867   output->append(hdrs.c_str(), hdrs.size());
868
869   return 0;
870 }
871
872 int HttpsUpstream::on_downstream_body(Downstream *downstream,
873                                       const uint8_t *data, size_t len,
874                                       bool flush) {
875   if (len == 0) {
876     return 0;
877   }
878   auto output = downstream->get_response_buf();
879   if (downstream->get_chunked_response()) {
880     auto chunk_size_hex = util::utox(len);
881     chunk_size_hex += "\r\n";
882
883     output->append(chunk_size_hex.c_str(), chunk_size_hex.size());
884   }
885   output->append(data, len);
886
887   downstream->add_response_sent_bodylen(len);
888
889   if (downstream->get_chunked_response()) {
890     output->append("\r\n");
891   }
892   return 0;
893 }
894
895 int HttpsUpstream::on_downstream_body_complete(Downstream *downstream) {
896   if (downstream->get_chunked_response()) {
897     auto output = downstream->get_response_buf();
898     auto &trailers = downstream->get_response_trailers();
899     if (trailers.empty()) {
900       output->append("0\r\n\r\n");
901     } else {
902       output->append("0\r\n");
903       std::string trailer_part;
904       http2::build_http1_headers_from_headers(trailer_part, trailers);
905       output->append(trailer_part.c_str(), trailer_part.size());
906       output->append("\r\n");
907     }
908   }
909   if (LOG_ENABLED(INFO)) {
910     DLOG(INFO, downstream) << "HTTP response completed";
911   }
912
913   if (!downstream->validate_response_bodylen()) {
914     downstream->set_response_connection_close(true);
915   }
916
917   if (downstream->get_request_connection_close() ||
918       downstream->get_response_connection_close()) {
919     auto handler = get_client_handler();
920     handler->set_should_close_after_write(true);
921   }
922   return 0;
923 }
924
925 int HttpsUpstream::on_downstream_abort_request(Downstream *downstream,
926                                                unsigned int status_code) {
927   error_reply(status_code);
928   handler_->signal_write();
929   return 0;
930 }
931
932 void HttpsUpstream::log_response_headers(const std::string &hdrs) const {
933   const char *hdrp;
934   std::string nhdrs;
935   if (log_config()->errorlog_tty) {
936     nhdrs = http::colorizeHeaders(hdrs.c_str());
937     hdrp = nhdrs.c_str();
938   } else {
939     hdrp = hdrs.c_str();
940   }
941   ULOG(INFO, this) << "HTTP response headers\n" << hdrp;
942 }
943
944 void HttpsUpstream::on_handler_delete() {
945   if (downstream_ && downstream_->accesslog_ready()) {
946     handler_->write_accesslog(downstream_.get());
947   }
948 }
949
950 int HttpsUpstream::on_downstream_reset(bool no_retry) {
951   int rv;
952
953   if (!downstream_->request_submission_ready()) {
954     // Return error so that caller can delete handler
955     return -1;
956   }
957
958   downstream_->pop_downstream_connection();
959
960   downstream_->add_retry();
961
962   if (no_retry || downstream_->no_more_retry()) {
963     goto fail;
964   }
965
966   rv = downstream_->attach_downstream_connection(
967       handler_->get_downstream_connection());
968   if (rv != 0) {
969     goto fail;
970   }
971
972   return 0;
973
974 fail:
975   if (on_downstream_abort_request(downstream_.get(), 503) != 0) {
976     return -1;
977   }
978   downstream_->pop_downstream_connection();
979
980   return 0;
981 }
982
983 } // namespace shrpx