xref: /aosp_15_r20/external/curl/lib/http1.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker 
25*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker 
27*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_HTTP
28*6236dae4SAndroid Build Coastguard Worker 
29*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
30*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
31*6236dae4SAndroid Build Coastguard Worker #include "http.h"
32*6236dae4SAndroid Build Coastguard Worker #include "http1.h"
33*6236dae4SAndroid Build Coastguard Worker #include "urlapi-int.h"
34*6236dae4SAndroid Build Coastguard Worker 
35*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
36*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
37*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
38*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
39*6236dae4SAndroid Build Coastguard Worker 
40*6236dae4SAndroid Build Coastguard Worker 
41*6236dae4SAndroid Build Coastguard Worker #define H1_MAX_URL_LEN   (8*1024)
42*6236dae4SAndroid Build Coastguard Worker 
Curl_h1_req_parse_init(struct h1_req_parser * parser,size_t max_line_len)43*6236dae4SAndroid Build Coastguard Worker void Curl_h1_req_parse_init(struct h1_req_parser *parser, size_t max_line_len)
44*6236dae4SAndroid Build Coastguard Worker {
45*6236dae4SAndroid Build Coastguard Worker   memset(parser, 0, sizeof(*parser));
46*6236dae4SAndroid Build Coastguard Worker   parser->max_line_len = max_line_len;
47*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&parser->scratch, max_line_len);
48*6236dae4SAndroid Build Coastguard Worker }
49*6236dae4SAndroid Build Coastguard Worker 
Curl_h1_req_parse_free(struct h1_req_parser * parser)50*6236dae4SAndroid Build Coastguard Worker void Curl_h1_req_parse_free(struct h1_req_parser *parser)
51*6236dae4SAndroid Build Coastguard Worker {
52*6236dae4SAndroid Build Coastguard Worker   if(parser) {
53*6236dae4SAndroid Build Coastguard Worker     Curl_http_req_free(parser->req);
54*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_free(&parser->scratch);
55*6236dae4SAndroid Build Coastguard Worker     parser->req = NULL;
56*6236dae4SAndroid Build Coastguard Worker     parser->done = FALSE;
57*6236dae4SAndroid Build Coastguard Worker   }
58*6236dae4SAndroid Build Coastguard Worker }
59*6236dae4SAndroid Build Coastguard Worker 
trim_line(struct h1_req_parser * parser,int options)60*6236dae4SAndroid Build Coastguard Worker static CURLcode trim_line(struct h1_req_parser *parser, int options)
61*6236dae4SAndroid Build Coastguard Worker {
62*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(parser->line);
63*6236dae4SAndroid Build Coastguard Worker   if(parser->line_len) {
64*6236dae4SAndroid Build Coastguard Worker     if(parser->line[parser->line_len - 1] == '\n')
65*6236dae4SAndroid Build Coastguard Worker       --parser->line_len;
66*6236dae4SAndroid Build Coastguard Worker     if(parser->line_len) {
67*6236dae4SAndroid Build Coastguard Worker       if(parser->line[parser->line_len - 1] == '\r')
68*6236dae4SAndroid Build Coastguard Worker         --parser->line_len;
69*6236dae4SAndroid Build Coastguard Worker       else if(options & H1_PARSE_OPT_STRICT)
70*6236dae4SAndroid Build Coastguard Worker         return CURLE_URL_MALFORMAT;
71*6236dae4SAndroid Build Coastguard Worker     }
72*6236dae4SAndroid Build Coastguard Worker     else if(options & H1_PARSE_OPT_STRICT)
73*6236dae4SAndroid Build Coastguard Worker       return CURLE_URL_MALFORMAT;
74*6236dae4SAndroid Build Coastguard Worker   }
75*6236dae4SAndroid Build Coastguard Worker   else if(options & H1_PARSE_OPT_STRICT)
76*6236dae4SAndroid Build Coastguard Worker     return CURLE_URL_MALFORMAT;
77*6236dae4SAndroid Build Coastguard Worker 
78*6236dae4SAndroid Build Coastguard Worker   if(parser->line_len > parser->max_line_len) {
79*6236dae4SAndroid Build Coastguard Worker     return CURLE_URL_MALFORMAT;
80*6236dae4SAndroid Build Coastguard Worker   }
81*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
82*6236dae4SAndroid Build Coastguard Worker }
83*6236dae4SAndroid Build Coastguard Worker 
detect_line(struct h1_req_parser * parser,const char * buf,const size_t buflen,CURLcode * err)84*6236dae4SAndroid Build Coastguard Worker static ssize_t detect_line(struct h1_req_parser *parser,
85*6236dae4SAndroid Build Coastguard Worker                            const char *buf, const size_t buflen,
86*6236dae4SAndroid Build Coastguard Worker                            CURLcode *err)
87*6236dae4SAndroid Build Coastguard Worker {
88*6236dae4SAndroid Build Coastguard Worker   const char  *line_end;
89*6236dae4SAndroid Build Coastguard Worker 
90*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(!parser->line);
91*6236dae4SAndroid Build Coastguard Worker   line_end = memchr(buf, '\n', buflen);
92*6236dae4SAndroid Build Coastguard Worker   if(!line_end) {
93*6236dae4SAndroid Build Coastguard Worker     *err = CURLE_AGAIN;
94*6236dae4SAndroid Build Coastguard Worker     return -1;
95*6236dae4SAndroid Build Coastguard Worker   }
96*6236dae4SAndroid Build Coastguard Worker   parser->line = buf;
97*6236dae4SAndroid Build Coastguard Worker   parser->line_len = line_end - buf + 1;
98*6236dae4SAndroid Build Coastguard Worker   *err = CURLE_OK;
99*6236dae4SAndroid Build Coastguard Worker   return (ssize_t)parser->line_len;
100*6236dae4SAndroid Build Coastguard Worker }
101*6236dae4SAndroid Build Coastguard Worker 
next_line(struct h1_req_parser * parser,const char * buf,const size_t buflen,int options,CURLcode * err)102*6236dae4SAndroid Build Coastguard Worker static ssize_t next_line(struct h1_req_parser *parser,
103*6236dae4SAndroid Build Coastguard Worker                          const char *buf, const size_t buflen, int options,
104*6236dae4SAndroid Build Coastguard Worker                          CURLcode *err)
105*6236dae4SAndroid Build Coastguard Worker {
106*6236dae4SAndroid Build Coastguard Worker   ssize_t nread = 0;
107*6236dae4SAndroid Build Coastguard Worker 
108*6236dae4SAndroid Build Coastguard Worker   if(parser->line) {
109*6236dae4SAndroid Build Coastguard Worker     parser->line = NULL;
110*6236dae4SAndroid Build Coastguard Worker     parser->line_len = 0;
111*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_reset(&parser->scratch);
112*6236dae4SAndroid Build Coastguard Worker   }
113*6236dae4SAndroid Build Coastguard Worker 
114*6236dae4SAndroid Build Coastguard Worker   nread = detect_line(parser, buf, buflen, err);
115*6236dae4SAndroid Build Coastguard Worker   if(nread >= 0) {
116*6236dae4SAndroid Build Coastguard Worker     if(Curl_dyn_len(&parser->scratch)) {
117*6236dae4SAndroid Build Coastguard Worker       /* append detected line to scratch to have the complete line */
118*6236dae4SAndroid Build Coastguard Worker       *err = Curl_dyn_addn(&parser->scratch, parser->line, parser->line_len);
119*6236dae4SAndroid Build Coastguard Worker       if(*err)
120*6236dae4SAndroid Build Coastguard Worker         return -1;
121*6236dae4SAndroid Build Coastguard Worker       parser->line = Curl_dyn_ptr(&parser->scratch);
122*6236dae4SAndroid Build Coastguard Worker       parser->line_len = Curl_dyn_len(&parser->scratch);
123*6236dae4SAndroid Build Coastguard Worker     }
124*6236dae4SAndroid Build Coastguard Worker     *err = trim_line(parser, options);
125*6236dae4SAndroid Build Coastguard Worker     if(*err)
126*6236dae4SAndroid Build Coastguard Worker       return -1;
127*6236dae4SAndroid Build Coastguard Worker   }
128*6236dae4SAndroid Build Coastguard Worker   else if(*err == CURLE_AGAIN) {
129*6236dae4SAndroid Build Coastguard Worker     /* no line end in `buf`, add it to our scratch */
130*6236dae4SAndroid Build Coastguard Worker     *err = Curl_dyn_addn(&parser->scratch, (const unsigned char *)buf, buflen);
131*6236dae4SAndroid Build Coastguard Worker     nread = (*err) ? -1 : (ssize_t)buflen;
132*6236dae4SAndroid Build Coastguard Worker   }
133*6236dae4SAndroid Build Coastguard Worker   return nread;
134*6236dae4SAndroid Build Coastguard Worker }
135*6236dae4SAndroid Build Coastguard Worker 
start_req(struct h1_req_parser * parser,const char * scheme_default,int options)136*6236dae4SAndroid Build Coastguard Worker static CURLcode start_req(struct h1_req_parser *parser,
137*6236dae4SAndroid Build Coastguard Worker                           const char *scheme_default, int options)
138*6236dae4SAndroid Build Coastguard Worker {
139*6236dae4SAndroid Build Coastguard Worker   const char  *p, *m, *target, *hv, *scheme, *authority, *path;
140*6236dae4SAndroid Build Coastguard Worker   size_t m_len, target_len, hv_len, scheme_len, authority_len, path_len;
141*6236dae4SAndroid Build Coastguard Worker   size_t i;
142*6236dae4SAndroid Build Coastguard Worker   CURLU *url = NULL;
143*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_URL_MALFORMAT; /* Use this as default fail */
144*6236dae4SAndroid Build Coastguard Worker 
145*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(!parser->req);
146*6236dae4SAndroid Build Coastguard Worker   /* line must match: "METHOD TARGET HTTP_VERSION" */
147*6236dae4SAndroid Build Coastguard Worker   p = memchr(parser->line, ' ', parser->line_len);
148*6236dae4SAndroid Build Coastguard Worker   if(!p || p == parser->line)
149*6236dae4SAndroid Build Coastguard Worker     goto out;
150*6236dae4SAndroid Build Coastguard Worker 
151*6236dae4SAndroid Build Coastguard Worker   m = parser->line;
152*6236dae4SAndroid Build Coastguard Worker   m_len = p - parser->line;
153*6236dae4SAndroid Build Coastguard Worker   target = p + 1;
154*6236dae4SAndroid Build Coastguard Worker   target_len = hv_len = 0;
155*6236dae4SAndroid Build Coastguard Worker   hv = NULL;
156*6236dae4SAndroid Build Coastguard Worker 
157*6236dae4SAndroid Build Coastguard Worker   /* URL may contain spaces so scan backwards */
158*6236dae4SAndroid Build Coastguard Worker   for(i = parser->line_len; i > m_len; --i) {
159*6236dae4SAndroid Build Coastguard Worker     if(parser->line[i] == ' ') {
160*6236dae4SAndroid Build Coastguard Worker       hv = &parser->line[i + 1];
161*6236dae4SAndroid Build Coastguard Worker       hv_len = parser->line_len - i;
162*6236dae4SAndroid Build Coastguard Worker       target_len = (hv - target) - 1;
163*6236dae4SAndroid Build Coastguard Worker       break;
164*6236dae4SAndroid Build Coastguard Worker     }
165*6236dae4SAndroid Build Coastguard Worker   }
166*6236dae4SAndroid Build Coastguard Worker   /* no SPACE found or empty TARGET or empty HTTP_VERSION */
167*6236dae4SAndroid Build Coastguard Worker   if(!target_len || !hv_len)
168*6236dae4SAndroid Build Coastguard Worker     goto out;
169*6236dae4SAndroid Build Coastguard Worker 
170*6236dae4SAndroid Build Coastguard Worker   /* TODO: we do not check HTTP_VERSION for conformity, should
171*6236dae4SAndroid Build Coastguard Worker    + do that when STRICT option is supplied. */
172*6236dae4SAndroid Build Coastguard Worker   (void)hv;
173*6236dae4SAndroid Build Coastguard Worker 
174*6236dae4SAndroid Build Coastguard Worker   /* The TARGET can be (rfc 9112, ch. 3.2):
175*6236dae4SAndroid Build Coastguard Worker    * origin-form:     path + optional query
176*6236dae4SAndroid Build Coastguard Worker    * absolute-form:   absolute URI
177*6236dae4SAndroid Build Coastguard Worker    * authority-form:  host+port for CONNECT
178*6236dae4SAndroid Build Coastguard Worker    * asterisk-form:   '*' for OPTIONS
179*6236dae4SAndroid Build Coastguard Worker    *
180*6236dae4SAndroid Build Coastguard Worker    * from TARGET, we derive `scheme` `authority` `path`
181*6236dae4SAndroid Build Coastguard Worker    * origin-form            --        --          TARGET
182*6236dae4SAndroid Build Coastguard Worker    * absolute-form          URL*      URL*        URL*
183*6236dae4SAndroid Build Coastguard Worker    * authority-form         --        TARGET      --
184*6236dae4SAndroid Build Coastguard Worker    * asterisk-form          --        --          TARGET
185*6236dae4SAndroid Build Coastguard Worker    */
186*6236dae4SAndroid Build Coastguard Worker   scheme = authority = path = NULL;
187*6236dae4SAndroid Build Coastguard Worker   scheme_len = authority_len = path_len = 0;
188*6236dae4SAndroid Build Coastguard Worker 
189*6236dae4SAndroid Build Coastguard Worker   if(target_len == 1 && target[0] == '*') {
190*6236dae4SAndroid Build Coastguard Worker     /* asterisk-form */
191*6236dae4SAndroid Build Coastguard Worker     path = target;
192*6236dae4SAndroid Build Coastguard Worker     path_len = target_len;
193*6236dae4SAndroid Build Coastguard Worker   }
194*6236dae4SAndroid Build Coastguard Worker   else if(!strncmp("CONNECT", m, m_len)) {
195*6236dae4SAndroid Build Coastguard Worker     /* authority-form */
196*6236dae4SAndroid Build Coastguard Worker     authority = target;
197*6236dae4SAndroid Build Coastguard Worker     authority_len = target_len;
198*6236dae4SAndroid Build Coastguard Worker   }
199*6236dae4SAndroid Build Coastguard Worker   else if(target[0] == '/') {
200*6236dae4SAndroid Build Coastguard Worker     /* origin-form */
201*6236dae4SAndroid Build Coastguard Worker     path = target;
202*6236dae4SAndroid Build Coastguard Worker     path_len = target_len;
203*6236dae4SAndroid Build Coastguard Worker   }
204*6236dae4SAndroid Build Coastguard Worker   else {
205*6236dae4SAndroid Build Coastguard Worker     /* origin-form OR absolute-form */
206*6236dae4SAndroid Build Coastguard Worker     CURLUcode uc;
207*6236dae4SAndroid Build Coastguard Worker     char tmp[H1_MAX_URL_LEN];
208*6236dae4SAndroid Build Coastguard Worker 
209*6236dae4SAndroid Build Coastguard Worker     /* default, unless we see an absolute URL */
210*6236dae4SAndroid Build Coastguard Worker     path = target;
211*6236dae4SAndroid Build Coastguard Worker     path_len = target_len;
212*6236dae4SAndroid Build Coastguard Worker 
213*6236dae4SAndroid Build Coastguard Worker     /* URL parser wants 0-termination */
214*6236dae4SAndroid Build Coastguard Worker     if(target_len >= sizeof(tmp))
215*6236dae4SAndroid Build Coastguard Worker       goto out;
216*6236dae4SAndroid Build Coastguard Worker     memcpy(tmp, target, target_len);
217*6236dae4SAndroid Build Coastguard Worker     tmp[target_len] = '\0';
218*6236dae4SAndroid Build Coastguard Worker     /* See if treating TARGET as an absolute URL makes sense */
219*6236dae4SAndroid Build Coastguard Worker     if(Curl_is_absolute_url(tmp, NULL, 0, FALSE)) {
220*6236dae4SAndroid Build Coastguard Worker       unsigned int url_options;
221*6236dae4SAndroid Build Coastguard Worker 
222*6236dae4SAndroid Build Coastguard Worker       url = curl_url();
223*6236dae4SAndroid Build Coastguard Worker       if(!url) {
224*6236dae4SAndroid Build Coastguard Worker         result = CURLE_OUT_OF_MEMORY;
225*6236dae4SAndroid Build Coastguard Worker         goto out;
226*6236dae4SAndroid Build Coastguard Worker       }
227*6236dae4SAndroid Build Coastguard Worker       url_options = (CURLU_NON_SUPPORT_SCHEME|
228*6236dae4SAndroid Build Coastguard Worker                      CURLU_PATH_AS_IS|
229*6236dae4SAndroid Build Coastguard Worker                      CURLU_NO_DEFAULT_PORT);
230*6236dae4SAndroid Build Coastguard Worker       if(!(options & H1_PARSE_OPT_STRICT))
231*6236dae4SAndroid Build Coastguard Worker         url_options |= CURLU_ALLOW_SPACE;
232*6236dae4SAndroid Build Coastguard Worker       uc = curl_url_set(url, CURLUPART_URL, tmp, url_options);
233*6236dae4SAndroid Build Coastguard Worker       if(uc) {
234*6236dae4SAndroid Build Coastguard Worker         goto out;
235*6236dae4SAndroid Build Coastguard Worker       }
236*6236dae4SAndroid Build Coastguard Worker     }
237*6236dae4SAndroid Build Coastguard Worker 
238*6236dae4SAndroid Build Coastguard Worker     if(!url && (options & H1_PARSE_OPT_STRICT)) {
239*6236dae4SAndroid Build Coastguard Worker       /* we should have an absolute URL or have seen `/` earlier */
240*6236dae4SAndroid Build Coastguard Worker       goto out;
241*6236dae4SAndroid Build Coastguard Worker     }
242*6236dae4SAndroid Build Coastguard Worker   }
243*6236dae4SAndroid Build Coastguard Worker 
244*6236dae4SAndroid Build Coastguard Worker   if(url) {
245*6236dae4SAndroid Build Coastguard Worker     result = Curl_http_req_make2(&parser->req, m, m_len, url, scheme_default);
246*6236dae4SAndroid Build Coastguard Worker   }
247*6236dae4SAndroid Build Coastguard Worker   else {
248*6236dae4SAndroid Build Coastguard Worker     if(!scheme && scheme_default) {
249*6236dae4SAndroid Build Coastguard Worker       scheme = scheme_default;
250*6236dae4SAndroid Build Coastguard Worker       scheme_len = strlen(scheme_default);
251*6236dae4SAndroid Build Coastguard Worker     }
252*6236dae4SAndroid Build Coastguard Worker     result = Curl_http_req_make(&parser->req, m, m_len, scheme, scheme_len,
253*6236dae4SAndroid Build Coastguard Worker                                 authority, authority_len, path, path_len);
254*6236dae4SAndroid Build Coastguard Worker   }
255*6236dae4SAndroid Build Coastguard Worker 
256*6236dae4SAndroid Build Coastguard Worker out:
257*6236dae4SAndroid Build Coastguard Worker   curl_url_cleanup(url);
258*6236dae4SAndroid Build Coastguard Worker   return result;
259*6236dae4SAndroid Build Coastguard Worker }
260*6236dae4SAndroid Build Coastguard Worker 
Curl_h1_req_parse_read(struct h1_req_parser * parser,const char * buf,size_t buflen,const char * scheme_default,int options,CURLcode * err)261*6236dae4SAndroid Build Coastguard Worker ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
262*6236dae4SAndroid Build Coastguard Worker                                const char *buf, size_t buflen,
263*6236dae4SAndroid Build Coastguard Worker                                const char *scheme_default, int options,
264*6236dae4SAndroid Build Coastguard Worker                                CURLcode *err)
265*6236dae4SAndroid Build Coastguard Worker {
266*6236dae4SAndroid Build Coastguard Worker   ssize_t nread = 0, n;
267*6236dae4SAndroid Build Coastguard Worker 
268*6236dae4SAndroid Build Coastguard Worker   *err = CURLE_OK;
269*6236dae4SAndroid Build Coastguard Worker   while(!parser->done) {
270*6236dae4SAndroid Build Coastguard Worker     n = next_line(parser, buf, buflen, options, err);
271*6236dae4SAndroid Build Coastguard Worker     if(n < 0) {
272*6236dae4SAndroid Build Coastguard Worker       if(*err != CURLE_AGAIN) {
273*6236dae4SAndroid Build Coastguard Worker         nread = -1;
274*6236dae4SAndroid Build Coastguard Worker       }
275*6236dae4SAndroid Build Coastguard Worker       *err = CURLE_OK;
276*6236dae4SAndroid Build Coastguard Worker       goto out;
277*6236dae4SAndroid Build Coastguard Worker     }
278*6236dae4SAndroid Build Coastguard Worker 
279*6236dae4SAndroid Build Coastguard Worker     /* Consume this line */
280*6236dae4SAndroid Build Coastguard Worker     nread += (size_t)n;
281*6236dae4SAndroid Build Coastguard Worker     buf += (size_t)n;
282*6236dae4SAndroid Build Coastguard Worker     buflen -= (size_t)n;
283*6236dae4SAndroid Build Coastguard Worker 
284*6236dae4SAndroid Build Coastguard Worker     if(!parser->line) {
285*6236dae4SAndroid Build Coastguard Worker       /* consumed bytes, but line not complete */
286*6236dae4SAndroid Build Coastguard Worker       if(!buflen)
287*6236dae4SAndroid Build Coastguard Worker         goto out;
288*6236dae4SAndroid Build Coastguard Worker     }
289*6236dae4SAndroid Build Coastguard Worker     else if(!parser->req) {
290*6236dae4SAndroid Build Coastguard Worker       *err = start_req(parser, scheme_default, options);
291*6236dae4SAndroid Build Coastguard Worker       if(*err) {
292*6236dae4SAndroid Build Coastguard Worker         nread = -1;
293*6236dae4SAndroid Build Coastguard Worker         goto out;
294*6236dae4SAndroid Build Coastguard Worker       }
295*6236dae4SAndroid Build Coastguard Worker     }
296*6236dae4SAndroid Build Coastguard Worker     else if(parser->line_len == 0) {
297*6236dae4SAndroid Build Coastguard Worker       /* last, empty line, we are finished */
298*6236dae4SAndroid Build Coastguard Worker       if(!parser->req) {
299*6236dae4SAndroid Build Coastguard Worker         *err = CURLE_URL_MALFORMAT;
300*6236dae4SAndroid Build Coastguard Worker         nread = -1;
301*6236dae4SAndroid Build Coastguard Worker         goto out;
302*6236dae4SAndroid Build Coastguard Worker       }
303*6236dae4SAndroid Build Coastguard Worker       parser->done = TRUE;
304*6236dae4SAndroid Build Coastguard Worker       Curl_dyn_reset(&parser->scratch);
305*6236dae4SAndroid Build Coastguard Worker       /* last chance adjustments */
306*6236dae4SAndroid Build Coastguard Worker     }
307*6236dae4SAndroid Build Coastguard Worker     else {
308*6236dae4SAndroid Build Coastguard Worker       *err = Curl_dynhds_h1_add_line(&parser->req->headers,
309*6236dae4SAndroid Build Coastguard Worker                                      parser->line, parser->line_len);
310*6236dae4SAndroid Build Coastguard Worker       if(*err) {
311*6236dae4SAndroid Build Coastguard Worker         nread = -1;
312*6236dae4SAndroid Build Coastguard Worker         goto out;
313*6236dae4SAndroid Build Coastguard Worker       }
314*6236dae4SAndroid Build Coastguard Worker     }
315*6236dae4SAndroid Build Coastguard Worker   }
316*6236dae4SAndroid Build Coastguard Worker 
317*6236dae4SAndroid Build Coastguard Worker out:
318*6236dae4SAndroid Build Coastguard Worker   return nread;
319*6236dae4SAndroid Build Coastguard Worker }
320*6236dae4SAndroid Build Coastguard Worker 
Curl_h1_req_write_head(struct httpreq * req,int http_minor,struct dynbuf * dbuf)321*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
322*6236dae4SAndroid Build Coastguard Worker                                 struct dynbuf *dbuf)
323*6236dae4SAndroid Build Coastguard Worker {
324*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
325*6236dae4SAndroid Build Coastguard Worker 
326*6236dae4SAndroid Build Coastguard Worker   result = Curl_dyn_addf(dbuf, "%s %s%s%s%s HTTP/1.%d\r\n",
327*6236dae4SAndroid Build Coastguard Worker                          req->method,
328*6236dae4SAndroid Build Coastguard Worker                          req->scheme ? req->scheme : "",
329*6236dae4SAndroid Build Coastguard Worker                          req->scheme ? "://" : "",
330*6236dae4SAndroid Build Coastguard Worker                          req->authority ? req->authority : "",
331*6236dae4SAndroid Build Coastguard Worker                          req->path ? req->path : "",
332*6236dae4SAndroid Build Coastguard Worker                          http_minor);
333*6236dae4SAndroid Build Coastguard Worker   if(result)
334*6236dae4SAndroid Build Coastguard Worker     goto out;
335*6236dae4SAndroid Build Coastguard Worker 
336*6236dae4SAndroid Build Coastguard Worker   result = Curl_dynhds_h1_dprint(&req->headers, dbuf);
337*6236dae4SAndroid Build Coastguard Worker   if(result)
338*6236dae4SAndroid Build Coastguard Worker     goto out;
339*6236dae4SAndroid Build Coastguard Worker 
340*6236dae4SAndroid Build Coastguard Worker   result = Curl_dyn_addn(dbuf, STRCONST("\r\n"));
341*6236dae4SAndroid Build Coastguard Worker 
342*6236dae4SAndroid Build Coastguard Worker out:
343*6236dae4SAndroid Build Coastguard Worker   return result;
344*6236dae4SAndroid Build Coastguard Worker }
345*6236dae4SAndroid Build Coastguard Worker 
346*6236dae4SAndroid Build Coastguard Worker #endif /* !CURL_DISABLE_HTTP */
347