From: Daniel Stenberg Date: Thu, 17 Mar 2022 16:55:06 +0000 (+0100) Subject: curl: add %{header_json} support in -w handling X-Git-Tag: curl-7_83_0~127 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4133a69f2daa476bb;p=thirdparty%2Fcurl.git curl: add %{header_json} support in -w handling Outputs all response headers as a JSON object. --- diff --git a/docs/cmdline-opts/write-out.d b/docs/cmdline-opts/write-out.d index 6d8ed44925..11f01b87a2 100644 --- a/docs/cmdline-opts/write-out.d +++ b/docs/cmdline-opts/write-out.d @@ -52,6 +52,9 @@ option. (Added in 7.26.0) The initial path curl ended up in when logging on to the remote FTP server. (Added in 7.15.4) .TP +.B header_json +A JSON object with all HTTP response headers from the recent transfer. +.TP .B http_code The numerical response code that was found in the last retrieved HTTP(S) or FTP(s) transfer. diff --git a/lib/headers.c b/lib/headers.c index 67ae00fb42..add23b786e 100644 --- a/lib/headers.c +++ b/lib/headers.c @@ -155,7 +155,8 @@ struct curl_header *curl_easy_nextheader(CURL *easy, hs = pick->ptr; if((hs->type & type) && (hs->request == request)) break; - } while((pick = pick->next)); + pick = pick->next; + } while(pick); } if(!pick) diff --git a/src/tool_writeout.c b/src/tool_writeout.c index c2e4095530..c2239efde1 100644 --- a/src/tool_writeout.c +++ b/src/tool_writeout.c @@ -75,6 +75,7 @@ static const struct writeoutvar variables[] = { {"exitcode", VAR_EXITCODE, 0, writeLong}, {"filename_effective", VAR_EFFECTIVE_FILENAME, 0, writeString}, {"ftp_entry_path", VAR_FTP_ENTRY_PATH, CURLINFO_FTP_ENTRY_PATH, writeString}, + {"header_json", VAR_HEADER_JSON, 0, NULL}, {"http_code", VAR_HTTP_CODE, CURLINFO_RESPONSE_CODE, writeLong}, {"http_connect", VAR_HTTP_CODE_PROXY, CURLINFO_HTTP_CONNECTCODE, writeLong}, {"http_version", VAR_HTTP_VERSION, CURLINFO_HTTP_VERSION, writeString}, @@ -218,9 +219,8 @@ static int writeString(FILE *stream, const struct writeoutvar *wovar, if(valid) { DEBUGASSERT(strinfo); if(use_json) { - fprintf(stream, "\"%s\":\"", wovar->name); + fprintf(stream, "\"%s\":", wovar->name); jsonWriteString(stream, strinfo); - fputs("\"", stream); } else fputs(strinfo, stream); @@ -366,6 +366,9 @@ void ourWriteOut(const char *writeinfo, struct per_transfer *per, case VAR_JSON: ourWriteOutJSON(stream, variables, per, per_result); break; + case VAR_HEADER_JSON: + headerJSON(stream, per); + break; default: (void)variables[i].writefunc(stream, &variables[i], per, per_result, false); diff --git a/src/tool_writeout.h b/src/tool_writeout.h index b8f51ffaa3..abf14e30b1 100644 --- a/src/tool_writeout.h +++ b/src/tool_writeout.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,6 +35,7 @@ typedef enum { VAR_ERRORMSG, VAR_EXITCODE, VAR_FTP_ENTRY_PATH, + VAR_HEADER_JSON, VAR_HEADER_SIZE, VAR_HTTP_CODE, VAR_HTTP_CODE_PROXY, diff --git a/src/tool_writeout_json.c b/src/tool_writeout_json.c index caa1ea6f3d..2ccc9942ef 100644 --- a/src/tool_writeout_json.c +++ b/src/tool_writeout_json.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -29,12 +29,12 @@ #include "tool_writeout_json.h" #include "tool_writeout.h" - void jsonWriteString(FILE *stream, const char *in) { const char *i = in; const char *in_end = in + strlen(in); + fputc('\"', stream); for(; i < in_end; i++) { switch(*i) { case '\\': @@ -68,6 +68,7 @@ void jsonWriteString(FILE *stream, const char *in) break; } } + fputc('\"', stream); } void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[], @@ -85,7 +86,54 @@ void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[], /* The variables are sorted in alphabetical order but as a special case curl_version (which is not actually a --write-out variable) is last. */ - fprintf(stream, "\"curl_version\":\""); + fprintf(stream, "\"curl_version\":"); jsonWriteString(stream, curl_version()); - fprintf(stream, "\"}"); + fprintf(stream, "}"); +} + +#ifdef _MSC_VER +/* warning C4706: assignment within conditional expression */ +#pragma warning(disable:4706) +#endif + +void headerJSON(FILE *stream, struct per_transfer *per) +{ + struct curl_header *header; + struct curl_header *prev = NULL; + + fputc('{', stream); + while((header = curl_easy_nextheader(per->curl, CURLH_HEADER, -1, + prev))) { + if(prev) + fputs(",\n", stream); + jsonWriteString(stream, header->name); + fputc(':', stream); + prev = header; + if(header->amount > 1) { + if(!header->index) { + /* act on the 0-index entry and pull the others in, then output in a + JSON list */ + size_t a = header->amount; + size_t i = 0; + char *name = header->name; + fputc('[', stream); + do { + jsonWriteString(stream, header->value); + if(++i >= a) + break; + fputc(',', stream); + if(curl_easy_header(per->curl, name, i, CURLH_HEADER, + -1, &header)) + break; + } while(1); + } + fputc(']', stream); + } + else { + fputc('[', stream); + jsonWriteString(stream, header->value); + fputc(']', stream); + } + } + fputs("\n}", stream); } diff --git a/src/tool_writeout_json.h b/src/tool_writeout_json.h index f6b3a86afe..f10e260b52 100644 --- a/src/tool_writeout_json.h +++ b/src/tool_writeout_json.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -26,7 +26,7 @@ void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[], struct per_transfer *per, CURLcode per_result); - +void headerJSON(FILE *stream, struct per_transfer *per); void jsonWriteString(FILE *stream, const char *in); #endif /* HEADER_CURL_TOOL_WRITEOUT_H */