Skip to content

Commit

Permalink
curl: add %{header_json} support in -w handling
Browse files Browse the repository at this point in the history
Outputs all response headers as a JSON object.
  • Loading branch information
bagder committed Mar 22, 2022
1 parent 2d45137 commit 4133a69
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 10 deletions.
3 changes: 3 additions & 0 deletions docs/cmdline-opts/write-out.d
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion lib/headers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 5 additions & 2 deletions src/tool_writeout.c
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion src/tool_writeout.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
Expand Down Expand Up @@ -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,
Expand Down
56 changes: 52 additions & 4 deletions src/tool_writeout_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
Expand All @@ -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 '\\':
Expand Down Expand Up @@ -68,6 +68,7 @@ void jsonWriteString(FILE *stream, const char *in)
break;
}
}
fputc('\"', stream);
}

void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[],
Expand All @@ -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);
}
4 changes: 2 additions & 2 deletions src/tool_writeout_json.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
Expand All @@ -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 */

0 comments on commit 4133a69

Please sign in to comment.