Skip to content

Commit b54ab72

Browse files
committed
lib/libfetch: Add fetchXReqHTTP(3)
Modern APIs often rely on HTTP fields as part of their interface, both in requests and responses. Add a function to libfetch allowing additional request fields to be specified for an HTTP request and response fields to be returned to the caller. This function accepts an optional stream for the body content, as a nul-terminated C string may be inadequate for some content. If the length of the stream can be determined, a Content-Length header is added. Otherwise, the body is sent chunk-encoded. Signed-off-by: Ryan Moeller <[email protected]>
1 parent 4fc1e75 commit b54ab72

File tree

5 files changed

+339
-38
lines changed

5 files changed

+339
-38
lines changed

lib/libfetch/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ httperr.h: http.errors ${.CURDIR}/Makefile
4848
@echo " { -1, FETCH_UNKNOWN, \"Unknown HTTP error\" }" >> ${.TARGET}
4949
@echo "};" >> ${.TARGET}
5050

51+
MLINKS+= fetch.3 fetchFreeResFields.3
5152
MLINKS+= fetch.3 fetchFreeURL.3
5253
MLINKS+= fetch.3 fetchGet.3
5354
MLINKS+= fetch.3 fetchGetFTP.3
@@ -77,5 +78,6 @@ MLINKS+= fetch.3 fetchXGetFTP.3
7778
MLINKS+= fetch.3 fetchXGetFile.3
7879
MLINKS+= fetch.3 fetchXGetHTTP.3
7980
MLINKS+= fetch.3 fetchXGetURL.3
81+
MLINKS+= fetch.3 fetchXReqHTTP.3
8082

8183
.include <bsd.lib.mk>

lib/libfetch/common.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,6 @@ int fetch_no_proxy_match(const char *);
161161
*/
162162
FILE *http_request(struct url *, const char *,
163163
struct url_stat *, struct url *, const char *);
164-
FILE *http_request_body(struct url *, const char *,
165-
struct url_stat *, struct url *, const char *,
166-
const char *, const char *);
167164
FILE *ftp_request(struct url *, const char *,
168165
struct url_stat *, struct url *, const char *);
169166

lib/libfetch/fetch.3

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2525
.\" SUCH DAMAGE.
2626
.\"
27-
.Dd October 7, 2023
27+
.Dd September 27, 2025
2828
.Dt FETCH 3
2929
.Os
3030
.Sh NAME
@@ -51,7 +51,9 @@
5151
.Nm fetchPutHTTP ,
5252
.Nm fetchStatHTTP ,
5353
.Nm fetchListHTTP ,
54+
.Nm fetchXReqHTTP ,
5455
.Nm fetchReqHTTP ,
56+
.Nm fetchFreeResFields ,
5557
.Nm fetchXGetFTP ,
5658
.Nm fetchGetFTP ,
5759
.Nm fetchPutFTP ,
@@ -62,6 +64,7 @@
6264
.Lb libfetch
6365
.Sh SYNOPSIS
6466
.In sys/param.h
67+
.In sys/queue.h
6568
.In stdio.h
6669
.In fetch.h
6770
.Ft struct url *
@@ -111,7 +114,11 @@
111114
.Ft struct url_ent *
112115
.Fn fetchListHTTP "struct url *u" "const char *flags"
113116
.Ft FILE *
117+
.Fn fetchXReqHTTP "struct url *u" "struct url_stat *us" "const char *method" "const char *flags" "const struct http_fields *req_headers" "const struct http_fields *req_trailers" "struct http_fields *res_headers" "struct http_fields *res_trailers" "FILE *body"
118+
.Ft FILE *
114119
.Fn fetchReqHTTP "struct url *u" "const char *method" "const char *flags" "const char *content_type" "const char *body"
120+
.Ft void
121+
.Fn fetchFreeResFields "struct http_fields *fields"
115122
.Ft FILE *
116123
.Fn fetchXGetFTP "struct url *u" "struct url_stat *us" "const char *flags"
117124
.Ft FILE *
@@ -357,7 +364,8 @@ and password "anonymous@<hostname>".
357364
The
358365
.Fn fetchXGetHTTP ,
359366
.Fn fetchGetHTTP ,
360-
.Fn fetchPutHTTP
367+
.Fn fetchPutHTTP ,
368+
.Fn fetchXReqHTTP ,
361369
and
362370
.Fn fetchReqHTTP
363371
functions implement the HTTP/1.1 protocol.
@@ -389,7 +397,18 @@ will send a conditional
389397
HTTP header to only fetch the content if it is newer than
390398
.Va ims_time .
391399
.Pp
392-
The function
400+
If the
401+
.Ql C
402+
(chunked) flag is specified,
403+
.Fn fetchXReqHTTP
404+
and
405+
.Fn fetchReqHTTP
406+
will send the provided body content as a chunk-encoded stream even if a size can
407+
be predetermined.
408+
.Pp
409+
The functions
410+
.Fn fetchXReqHTTP
411+
and
393412
.Fn fetchReqHTTP
394413
can be used to make requests with an arbitrary HTTP verb,
395414
including POST, DELETE, CONNECT, OPTIONS, TRACE or PATCH.
@@ -401,10 +420,32 @@ and
401420
.Fa body
402421
to the content.
403422
.Pp
404-
Since there seems to be no good way of implementing the HTTP PUT
405-
method in a manner consistent with the rest of the
406-
.Nm fetch
407-
library,
423+
In addition to returning
424+
.Vt "struct url_stat"
425+
information,
426+
.Fn fetchXReqHTTP
427+
also accepts optional lists of arbitrary additional fields to send,
428+
optional lists to be filled with all response fields received,
429+
and an optional
430+
.Vt "FILE"
431+
stream to send as the body.
432+
The response fields lists should be freed with
433+
.Fn fetchFreeResFields .
434+
The
435+
.Vt http_field
436+
and
437+
.Vt http_fields
438+
structures are defined as follows in
439+
.In fetch.h :
440+
.Bd -literal
441+
struct http_field {
442+
const char *name;
443+
const char *value;
444+
TAILQ_ENTRY(http_field) fields;
445+
};
446+
TAILQ_HEAD(http_fields, http_field);
447+
.Ed
448+
.Pp
408449
.Fn fetchPutHTTP
409450
is currently unimplemented.
410451
.Sh HTTPS SCHEME

lib/libfetch/fetch.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#ifndef _FETCH_H_INCLUDED
3232
#define _FETCH_H_INCLUDED
3333

34-
#define _LIBFETCH_VER "libfetch/2.0"
34+
#define _LIBFETCH_VER "libfetch/2.1"
3535

3636
#define URL_SCHEMELEN 16
3737
#define URL_USERLEN 256
@@ -61,6 +61,15 @@ struct url_ent {
6161
struct url_stat stat;
6262
};
6363

64+
#ifdef _SYS_QUEUE_H_
65+
struct http_field {
66+
const char *name;
67+
const char *value;
68+
TAILQ_ENTRY(http_field) fields;
69+
};
70+
TAILQ_HEAD(http_fields, http_field);
71+
#endif
72+
6473
/* Recognized schemes */
6574
#define SCHEME_FTP "ftp"
6675
#define SCHEME_HTTP "http"
@@ -105,6 +114,13 @@ int fetchStatHTTP(struct url *, struct url_stat *, const char *);
105114
struct url_ent *fetchListHTTP(struct url *, const char *);
106115
FILE *fetchReqHTTP(struct url *, const char *, const char *,
107116
const char *, const char *);
117+
#ifdef _SYS_QUEUE_H_
118+
FILE *fetchXReqHTTP(struct url *, struct url_stat *, const char *,
119+
const char *, const struct http_fields *,
120+
const struct http_fields *, struct http_fields *,
121+
struct http_fields *, FILE *);
122+
void fetchFreeResFields(struct http_fields *);
123+
#endif
108124

109125
/* FTP-specific functions */
110126
FILE *fetchXGetFTP(struct url *, struct url_stat *, const char *);

0 commit comments

Comments
 (0)