1---
2c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
3SPDX-License-Identifier: curl
4Title: CURLOPT_DEBUGFUNCTION
5Section: 3
6Source: libcurl
7See-also:
8  - CURLINFO_CONN_ID (3)
9  - CURLINFO_XFER_ID (3)
10  - CURLOPT_DEBUGDATA (3)
11  - CURLOPT_VERBOSE (3)
12  - curl_global_trace (3)
13Protocol:
14  - All
15---
16
17# NAME
18
19CURLOPT_DEBUGFUNCTION - debug callback
20
21# SYNOPSIS
22
23~~~c
24#include <curl/curl.h>
25
26typedef enum {
27  CURLINFO_TEXT = 0,
28  CURLINFO_HEADER_IN,    /* 1 */
29  CURLINFO_HEADER_OUT,   /* 2 */
30  CURLINFO_DATA_IN,      /* 3 */
31  CURLINFO_DATA_OUT,     /* 4 */
32  CURLINFO_SSL_DATA_IN,  /* 5 */
33  CURLINFO_SSL_DATA_OUT, /* 6 */
34  CURLINFO_END
35} curl_infotype;
36
37int debug_callback(CURL *handle,
38                   curl_infotype type,
39                   char *data,
40                   size_t size,
41                   void *clientp);
42
43CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DEBUGFUNCTION,
44                          debug_callback);
45~~~
46
47# DESCRIPTION
48
49Pass a pointer to your callback function, which should match the prototype
50shown above.
51
52CURLOPT_DEBUGFUNCTION(3) replaces the standard debug function used when
53CURLOPT_VERBOSE(3) is in effect. This callback receives debug
54information, as specified in the *type* argument. This function must
55return 0. The *data* pointed to by the char * passed to this function is
56not null-terminated, but is exactly of the *size* as told by the
57*size* argument.
58
59The *clientp* argument is the pointer set with CURLOPT_DEBUGDATA(3).
60
61Available **curl_infotype** values:
62
63## CURLINFO_TEXT
64
65The data is informational text.
66
67## CURLINFO_HEADER_IN
68
69The data is header (or header-like) data received from the peer.
70
71## CURLINFO_HEADER_OUT
72
73The data is header (or header-like) data sent to the peer.
74
75## CURLINFO_DATA_IN
76
77The data is the unprocessed protocol data received from the peer. Even if the
78data is encoded or compressed, it is not provided decoded nor decompressed
79to this callback. If you need the data in decoded and decompressed form, use
80CURLOPT_WRITEFUNCTION(3).
81
82## CURLINFO_DATA_OUT
83
84The data is protocol data sent to the peer.
85
86## CURLINFO_SSL_DATA_OUT
87
88The data is SSL/TLS (binary) data sent to the peer.
89
90## CURLINFO_SSL_DATA_IN
91
92The data is SSL/TLS (binary) data received from the peer.
93
94WARNING: This callback may be called with the curl *handle* set to an
95internal handle. (Added in 8.4.0)
96
97If you need to distinguish your curl *handle* from internal handles then
98set CURLOPT_PRIVATE(3) on your handle.
99
100# DEFAULT
101
102NULL
103
104# EXAMPLE
105
106~~~c
107static
108void dump(const char *text,
109          FILE *stream, unsigned char *ptr, size_t size)
110{
111  size_t i;
112  size_t c;
113  unsigned int width = 0x10;
114
115  fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\n",
116          text, (long)size, (long)size);
117
118  for(i = 0; i < size; i += width) {
119    fprintf(stream, "%4.4lx: ", (long)i);
120
121    /* show hex to the left */
122    for(c = 0; c < width; c++) {
123      if(i + c < size)
124        fprintf(stream, "%02x ", ptr[i + c]);
125      else
126        fputs("   ", stream);
127    }
128
129    /* show data on the right */
130    for(c = 0; (c < width) && (i + c < size); c++) {
131      char x = (ptr[i + c] >= 0x20 && ptr[i + c] < 0x80) ? ptr[i + c] : '.';
132      fputc(x, stream);
133    }
134
135    fputc('\n', stream); /* newline */
136  }
137}
138
139static
140int my_trace(CURL *handle, curl_infotype type,
141             char *data, size_t size,
142             void *clientp)
143{
144  const char *text;
145  (void)handle; /* prevent compiler warning */
146  (void)clientp;
147
148  switch(type) {
149  case CURLINFO_TEXT:
150    fputs("== Info: ", stderr);
151    fwrite(data, size, 1, stderr);
152  default: /* in case a new one is introduced to shock us */
153    return 0;
154
155  case CURLINFO_HEADER_OUT:
156    text = "=> Send header";
157    break;
158  case CURLINFO_DATA_OUT:
159    text = "=> Send data";
160    break;
161  case CURLINFO_SSL_DATA_OUT:
162    text = "=> Send SSL data";
163    break;
164  case CURLINFO_HEADER_IN:
165    text = "<= Recv header";
166    break;
167  case CURLINFO_DATA_IN:
168    text = "<= Recv data";
169    break;
170  case CURLINFO_SSL_DATA_IN:
171    text = "<= Recv SSL data";
172    break;
173  }
174
175  dump(text, stderr, (unsigned char *)data, size);
176  return 0;
177}
178
179int main(void)
180{
181  CURL *curl;
182  CURLcode res;
183
184  curl = curl_easy_init();
185  if(curl) {
186    curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
187
188    /* the DEBUGFUNCTION has no effect until we enable VERBOSE */
189    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
190
191    /* example.com is redirected, so we tell libcurl to follow redirection */
192    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
193
194    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
195    res = curl_easy_perform(curl);
196    /* Check for errors */
197    if(res != CURLE_OK)
198      fprintf(stderr, "curl_easy_perform() failed: %s\n",
199              curl_easy_strerror(res));
200
201    /* always cleanup */
202    curl_easy_cleanup(curl);
203  }
204  return 0;
205}
206~~~
207
208# AVAILABILITY
209
210Always
211
212# RETURN VALUE
213
214Returns CURLE_OK
215