Skip to content

Commit d1e4a67

Browse files
committed
header api: add curl_easy_header and curl_easy_nextheader
Add test 1940 to 1946 to verify. Closes #8593
1 parent bdc664a commit d1e4a67

38 files changed

+1793
-301
lines changed

docs/EXPERIMENTAL.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ Experimental support in curl means:
2020

2121
- The Hyper HTTP backend
2222
- HTTP/3 support and options
23-
- CURLSSLOPT_NATIVE_CA (No configure option, feature built in when supported)
23+
- `CURLSSLOPT_NATIVE_CA` (No configure option, feature built in when supported)
24+
- The headers API: `curl_easy_header` and `curl_easy_nextheader`.

docs/examples/Makefile.inc

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ check_PROGRAMS = \
4444
getinmemory \
4545
getredirect \
4646
getreferrer \
47+
headerapi \
4748
http-post \
4849
http2-download \
4950
http2-pushinmemory \

docs/examples/headerapi.c

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/***************************************************************************
2+
* _ _ ____ _
3+
* Project ___| | | | _ \| |
4+
* / __| | | | |_) | |
5+
* | (__| |_| | _ <| |___
6+
* \___|\___/|_| \_\_____|
7+
*
8+
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
9+
*
10+
* This software is licensed as described in the file COPYING, which
11+
* you should have received as part of this distribution. The terms
12+
* are also available at https://curl.se/docs/copyright.html.
13+
*
14+
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
15+
* copies of the Software, and permit persons to whom the Software is
16+
* furnished to do so, under the terms of the COPYING file.
17+
*
18+
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19+
* KIND, either express or implied.
20+
*
21+
***************************************************************************/
22+
/* <DESC>
23+
* Extract headers post transfer with the header API
24+
* </DESC>
25+
*/
26+
#include <stdio.h>
27+
#include <curl/curl.h>
28+
29+
static size_t write_cb(char *data, size_t n, size_t l, void *userp)
30+
{
31+
/* take care of the data here, ignored in this example */
32+
(void)data;
33+
(void)userp;
34+
return n*l;
35+
}
36+
37+
int main(void)
38+
{
39+
CURL *curl;
40+
41+
curl = curl_easy_init();
42+
if(curl) {
43+
CURLcode res;
44+
struct curl_header *header;
45+
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
46+
/* example.com is redirected, so we tell libcurl to follow redirection */
47+
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
48+
49+
/* this example just ignores the content */
50+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
51+
52+
/* Perform the request, res will get the return code */
53+
res = curl_easy_perform(curl);
54+
/* Check for errors */
55+
if(res != CURLE_OK)
56+
fprintf(stderr, "curl_easy_perform() failed: %s\n",
57+
curl_easy_strerror(res));
58+
59+
if(CURLHE_OK == curl_easy_header(curl, "Content-Type", 0, CURLH_HEADER,
60+
-1, &header))
61+
printf("Got content-type: %s\n", header->value);
62+
63+
printf("All server headers:\n");
64+
{
65+
struct curl_header *h;
66+
struct curl_header *prev = NULL;
67+
do {
68+
h = curl_easy_nextheader(curl, CURLH_HEADER, -1, prev);
69+
if(h)
70+
printf(" %s: %s (%u)\n", h->name, h->value, (int)h->amount);
71+
prev = h;
72+
} while(h);
73+
74+
}
75+
/* always cleanup */
76+
curl_easy_cleanup(curl);
77+
}
78+
return 0;
79+
}

docs/libcurl/Makefile.inc

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# | (__| |_| | _ <| |___
66
# \___|\___/|_| \_\_____|
77
#
8-
# Copyright (C) 2008 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
8+
# Copyright (C) 2008 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
99
#
1010
# This software is licensed as described in the file COPYING, which
1111
# you should have received as part of this distribution. The terms
@@ -27,7 +27,9 @@ man_MANS = \
2727
curl_easy_duphandle.3 \
2828
curl_easy_escape.3 \
2929
curl_easy_getinfo.3 \
30+
curl_easy_header.3 \
3031
curl_easy_init.3 \
32+
curl_easy_nextheader.3 \
3133
curl_easy_option_by_id.3 \
3234
curl_easy_option_by_name.3 \
3335
curl_easy_option_next.3 \

docs/libcurl/curl_easy_header.3

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
.\" **************************************************************************
2+
.\" * _ _ ____ _
3+
.\" * Project ___| | | | _ \| |
4+
.\" * / __| | | | |_) | |
5+
.\" * | (__| |_| | _ <| |___
6+
.\" * \___|\___/|_| \_\_____|
7+
.\" *
8+
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
9+
.\" *
10+
.\" * This software is licensed as described in the file COPYING, which
11+
.\" * you should have received as part of this distribution. The terms
12+
.\" * are also available at https://curl.se/docs/copyright.html.
13+
.\" *
14+
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15+
.\" * copies of the Software, and permit persons to whom the Software is
16+
.\" * furnished to do so, under the terms of the COPYING file.
17+
.\" *
18+
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19+
.\" * KIND, either express or implied.
20+
.\" *
21+
.\" **************************************************************************
22+
.TH curl_easy_header 3 "13 March 2022" "libcurl 7.83.0" "libcurl Manual"
23+
.SH NAME
24+
curl_easy_header - get a HTTP header
25+
.SH SYNOPSIS
26+
.nf
27+
#include <curl/curl.h>
28+
29+
CURLHcode curl_easy_header(CURL *easy,
30+
const char *name,
31+
size_t index,
32+
unsigned int origin,
33+
int request,
34+
struct curl_header **hout);
35+
.SH DESCRIPTION
36+
EXPERIMENTAL feature!
37+
38+
\fIcurl_easy_header(3)\fP returns a pointer to a "curl_header" struct in
39+
\fBhout\fP with data for the HTTP response header \fIname\fP. The case
40+
insensitive nul-terminated header name should be specified without colon.
41+
42+
\fIindex\fP 0 means asking for the first instance of the header. If the
43+
returned header struct has \fBamount\fP set larger than 1, it means there are
44+
more instances of the same header name available to get. Asking for a too big
45+
index makes \fBCURLHE_BADINDEX\fP get returned.
46+
47+
The \fIorigin\fP argument is for specifying which headers to receive, as a
48+
single HTTP transfer might provide headers from several different places and
49+
they may then have different importance to the user and headers using the same
50+
name might be used. The \fIorigin\fP is a bitmask for what header sources you
51+
want. See the descriptions below.
52+
53+
The \fIrequest\fP argument tells libcurl from which request you want headers
54+
from. A single transfer might consist of a series of HTTP requests and this
55+
argument lets you specify which particular invidual request you want the
56+
headers from. 0 being the first request and then the number increases for
57+
further redirects or when multi-state authentication is used. Passing in -1 is
58+
a shortcut to "the last" request in the series, independently of the actual
59+
amount of requests used.
60+
61+
libcurl stores and provides the actually used "correct" headers. If for
62+
example two headers with the same name arrive and the latter overrides the
63+
former, then only the latter will be provided. If the first header survives
64+
the second, then only the first one will be provided. An application using
65+
this API does not have to bother about multiple headers used wrongly.
66+
67+
The memory for the returned struct is associated with the easy handle and
68+
subsequent calls to \fIcurl_easy_header(3)\fP will clobber the struct used in
69+
the previous calls for the same easy handle. Applications need to copy the
70+
data if it wants to keep it around. The memory used for the struct gets freed
71+
with calling \fIcurl_easy_cleanup(3)\fP of the easy handle.
72+
73+
The first line in a HTTP response is called the status line. It is not
74+
considered a header by this function. Headers are the "name: value" lines
75+
following the status.
76+
77+
This function can be used before (all) headers have been received and is fine
78+
to call from within libcurl callbacks. It will always return the state of the
79+
headers at the time it is called.
80+
.SH "The header struct"
81+
.nf
82+
struct curl_header {
83+
char *name;
84+
char *value;
85+
size_t amount;
86+
size_t index;
87+
unsigned int origin;
88+
void *anchor;
89+
};
90+
.fi
91+
92+
The data \fBname\fP field points to, will be the same as the requested name
93+
but it might have a different case.
94+
95+
The data \fBvalue\fP field points to, comes exactly as delivered over the
96+
network but with leading and trailing whitespace and newlines stripped
97+
off. The `value` data is nul-terminated.
98+
99+
\fBamount\fP is how many headers using this name that exist, within the origin
100+
and request scope asked for.
101+
102+
\fBindex\fP is the zero based entry number of this particular header, which in
103+
case this header was used more than once in the requested scope can be larger
104+
than 0 but is always less than \fBamount\fP.
105+
106+
The \fBorigin\fP field in the "curl_header" struct has one of the origin bits
107+
set, indicating where from the header originates. At the time of this writing,
108+
there are 5 bits with defined use. The undocumented 27 remaining bits are
109+
reserved for future use and must not be assumed to have any particular value.
110+
111+
\fBanchor\fP is a private handle used by libcurl internals. Do not modify.
112+
.SH ORIGINS
113+
.IP CURLH_HEADER
114+
The header arrived as a header from the server.
115+
.IP CURLH_TRAILER
116+
The header arrived as a trailer. A header that arrives after the body.
117+
.IP CURLH_CONNECT
118+
The header arrived in a CONNECT response. A CONNECT request is being done to
119+
setup a transfer "through" a HTTP(S) proxy.
120+
.IP CURLH_1XX
121+
The header arrived in a HTTP 1xx response. A 1xx response is an "intermediate"
122+
response that might happen before the "real" response.
123+
.IP CURLH_PSUEDO
124+
The header is a HTTP/2 or HTTP/3 pseudo header
125+
.SH EXAMPLE
126+
.nf
127+
struct curl_header *type;
128+
CURLHcode h =
129+
curl_easy_header(easy, "Content-Type", 0, CURLH_HEADER, -1, &type);
130+
.fi
131+
.SH AVAILABILITY
132+
Added in 7.83.0
133+
.SH RETURN VALUE
134+
This function returns a CURLHcode indiciating success or error.
135+
.IP "CURLHE_BADINDEX (1)"
136+
There is no header with the requested index.
137+
.IP "CURLHE_MISSING (2)"
138+
No such header exists.
139+
.IP "CURLHE_NOHEADERS (3)"
140+
No headers at all have been recorded.
141+
.IP "CURLHE_NOREQUEST (4)"
142+
There was no such request number.
143+
.IP "CURLHE_OUT_OF_MEMORY (5)"
144+
Out of resources
145+
.IP "CURLHE_BAD_ARGUMENT (6)"
146+
One or more of the given arguments are bad.
147+
.IP "CURLHE_NOT_BUILT_IN (7)"
148+
HTTP or the header API has been disbled in the build.
149+
.SH "SEE ALSO"
150+
.BR curl_easy_nextheader "(3), " curl_easy_perform "(3), "
151+
.BR CURLOPT_HEADERFUNCTION "(3), " CURLINFO_CONTENT_TYPE "(3) "

docs/libcurl/curl_easy_nextheader.3

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
.\" **************************************************************************
2+
.\" * _ _ ____ _
3+
.\" * Project ___| | | | _ \| |
4+
.\" * / __| | | | |_) | |
5+
.\" * | (__| |_| | _ <| |___
6+
.\" * \___|\___/|_| \_\_____|
7+
.\" *
8+
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
9+
.\" *
10+
.\" * This software is licensed as described in the file COPYING, which
11+
.\" * you should have received as part of this distribution. The terms
12+
.\" * are also available at https://curl.se/docs/copyright.html.
13+
.\" *
14+
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15+
.\" * copies of the Software, and permit persons to whom the Software is
16+
.\" * furnished to do so, under the terms of the COPYING file.
17+
.\" *
18+
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19+
.\" * KIND, either express or implied.
20+
.\" *
21+
.\" **************************************************************************
22+
.TH curl_easy_nextheader 3 "13 March 2022" "libcurl 7.83.0" "libcurl Manual"
23+
.SH NAME
24+
curl_easy_nextheader - get the next HTTP header
25+
.SH SYNOPSIS
26+
.nf
27+
#include <curl/curl.h>
28+
29+
struct curl_header *curl_easy_nextheader(CURL *easy,
30+
unsigned int origin,
31+
int request,
32+
struct curl_header *prev);
33+
.fi
34+
.SH DESCRIPTION
35+
EXPERIMENTAL feature!
36+
37+
This function lets an application iterate over all previously received HTTP
38+
headers.
39+
40+
The \fIorigin\fP argument is for specifying which headers to receive, as a
41+
single HTTP transfer might provide headers from several different places and
42+
they may then have different importance to the user and headers using the same
43+
name might be used. The \fIorigin\fP is a bitmask for what header sources you
44+
want. See the \fIcurl_easy_header(3)\fP man page for the origin descriptions.
45+
46+
The \fIrequest\fP argument tells libcurl from which request you want headers
47+
from. A single transfer might consist of a series of HTTP requests and this
48+
argument lets you specify which particular invidual request you want the
49+
headers from. 0 being the first request and then the number increases for
50+
further redirects or when multi-state authentication is used. Passing in -1 is
51+
a shortcut to "the last" request in the series, independently of the actual
52+
amount of requests used.
53+
54+
It is suggested that you pass in the same \fBorigin\fP and \fBrequest\fP when
55+
iterating over a range of headers as changing the value mid-loop might give
56+
you unexpected results.
57+
58+
If \fIprev\fP is NULL, this function returns a pointer to the first header
59+
stored within the given scope (origin + request).
60+
61+
If \fIprev\fP is a pointer to a previously returned header struct,
62+
\fIcurl_easy_nextheader(3)\fP returns a pointer the next header stored within
63+
the given scope. This way, an application can iterate over all availble
64+
headers.
65+
66+
The memory for the struct this points to, is owned and managed by libcurl and
67+
is associated with the easy handle. Applications must copy the data if they
68+
want it to survive subsequent API calls or the life-time of the easy handle.
69+
.SH EXAMPLE
70+
.nf
71+
struct curl_header *prev = NULL;
72+
struct curl_header *h;
73+
74+
/* extract the normal headers from the first request */
75+
while((h = curl_easy_nextheader(easy, CURLH_HEADER, 0, prev))) {
76+
print "%s: %s\\n", h->name, h->value);
77+
prev = h;
78+
}
79+
80+
/* extract the normal headers + 1xx + trailers from the last request */
81+
unsigned int origin = CURLH_HEADER| CURLH_1XX | CURLH_TRAILER;
82+
while((h = curl_easy_nextheader(easy, origin, -1, prev))) {
83+
print "%s: %s\\n", h->name, h->value);
84+
prev = h;
85+
}
86+
.fi
87+
.SH AVAILABILITY
88+
Added in 7.83.0
89+
.SH RETURN VALUE
90+
This function returns the next header, or NULL when there are no more
91+
(matching) headers or an error occurred.
92+
93+
If this function returns NULL when \fIprev\fP was set to NULL, then there are
94+
no headers available within the scope to return.
95+
.SH "SEE ALSO"
96+
.BR curl_easy_header "(3), " curl_easy_perform "(3) "

docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
.\" * | (__| |_| | _ <| |___
66
.\" * \___|\___/|_| \_\_____|
77
.\" *
8-
.\" * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
8+
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
99
.\" *
1010
.\" * This software is licensed as described in the file COPYING, which
1111
.\" * you should have received as part of this distribution. The terms
@@ -65,3 +65,4 @@ Added in 7.9.4
6565
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
6666
.SH "SEE ALSO"
6767
.BR curl_easy_getinfo "(3), " curl_easy_setopt "(3), "
68+
.BR CURLOPT_HEADERFUNCTION "(3), " curl_easy_header "(3) "

docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
.\" * | (__| |_| | _ <| |___
66
.\" * \___|\___/|_| \_\_____|
77
.\" *
8-
.\" * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
8+
.\" * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
99
.\" *
1010
.\" * This software is licensed as described in the file COPYING, which
1111
.\" * you should have received as part of this distribution. The terms
@@ -117,4 +117,5 @@ Always
117117
.SH RETURN VALUE
118118
Returns CURLE_OK
119119
.SH "SEE ALSO"
120+
.BR curl_easy_header "(3), "
120121
.BR CURLOPT_HEADERDATA "(3), " CURLOPT_WRITEFUNCTION "(3), "

0 commit comments

Comments
 (0)