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