3 Copyright (C) 1999-2005, Joe Orton <joe@manyfish.co.uk>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 #include "ne_utils.h" /* For ne_status */
26 #include "ne_string.h" /* For ne_buffer */
27 #include "ne_session.h"
31 #define NE_OK (0) /* Success */
32 #define NE_ERROR (1) /* Generic error; use ne_get_error(session) for message */
33 #define NE_LOOKUP (2) /* Server or proxy hostname lookup failed */
34 #define NE_AUTH (3) /* User authentication failed on server */
35 #define NE_PROXYAUTH (4) /* User authentication failed on proxy */
36 #define NE_CONNECT (5) /* Could not connect to server */
37 #define NE_TIMEOUT (6) /* Connection timed out */
38 #define NE_FAILED (7) /* The precondition failed */
39 #define NE_RETRY (8) /* Retry request (ne_end_request ONLY) */
40 #define NE_REDIRECT (9) /* See ne_redirect.h */
42 /* Opaque object representing a single HTTP request. */
43 typedef struct ne_request_s ne_request
;
45 /***** Request Handling *****/
47 /* Create a request in session 'sess', with given method and path.
48 * 'path' must conform to the 'abs_path' grammar in RFC2396, with an
49 * optional "? query" part, and MUST be URI-escaped by the caller. */
50 ne_request
*ne_request_create(ne_session
*sess
,
51 const char *method
, const char *path
);
53 /* The request body will be taken from 'size' bytes of 'buffer'. */
54 void ne_set_request_body_buffer(ne_request
*req
, const char *buffer
,
57 /* The request body will be taken from 'length' bytes read from the
58 * file descriptor 'fd', starting from file offset 'offset'. */
59 void ne_set_request_body_fd(ne_request
*req
, int fd
,
60 off_t offset
, off_t length
);
63 /* Alternate version of ne_set_request_body_fd taking off64_t
64 * offset type for systems supporting _LARGEFILE64_SOURCE. */
65 void ne_set_request_body_fd64(ne_request
*req
, int fd
,
66 off64_t offset
, off64_t length
);
69 /* "Pull"-based request body provider: a callback which is invoked to
70 * provide blocks of request body on demand.
72 * Before each time the body is provided, the callback will be called
73 * once with buflen == 0. The body may have to be provided >1 time
74 * per request (for authentication retries etc.).
76 * For a call with buflen == 0, the callback must return zero on success
77 * or non-zero on error; the session error string must be set on error.
78 * For a call with buflen > 0, the callback must return:
79 * <0 : error, abort request; session error string must be set.
80 * 0 : ignore 'buffer' contents, end of body.
81 * 0 < x <= buflen : buffer contains x bytes of body data. */
82 typedef ssize_t (*ne_provide_body
)(void *userdata
,
83 char *buffer
, size_t buflen
);
85 /* Install a callback which is invoked as needed to provide the
86 * request body, a block at a time. The total size of the request
87 * body is 'length'; the callback must ensure that it returns no more
88 * than 'length' bytes in total. */
89 void ne_set_request_body_provider(ne_request
*req
, off_t length
,
90 ne_provide_body provider
, void *userdata
);
93 /* Duplicate version of ne_set_request_body_provider, taking an off64_t
95 void ne_set_request_body_provider64(ne_request
*req
, off64_t length
,
96 ne_provide_body provider
, void *userdata
);
99 /* Handling response bodies; two callbacks must be provided:
101 * 1) 'acceptance' callback: determines whether you want to handle the
102 * response body given the response-status information, e.g., if you
103 * only want 2xx responses, say so here.
105 * 2) 'reader' callback: passed blocks of the response-body as they
106 * arrive, if the acceptance callback returned non-zero. */
108 /* 'acceptance' callback type. Return non-zero to accept the response,
109 * else zero to ignore it. */
110 typedef int (*ne_accept_response
)(void *userdata
, ne_request
*req
,
111 const ne_status
*st
);
113 /* An 'acceptance' callback which only accepts 2xx-class responses.
114 * Ignores userdata. */
115 int ne_accept_2xx(void *userdata
, ne_request
*req
, const ne_status
*st
);
117 /* An acceptance callback which accepts all responses. Ignores
119 int ne_accept_always(void *userdata
, ne_request
*req
, const ne_status
*st
);
121 /* Callback for reading a block of data. Returns zero on success, or
122 * non-zero on error. If returning an error, the response will be
123 * aborted and the callback will not be invoked again. The request
124 * dispatch (or ne_read_response_block call) will fail with NE_ERROR;
125 * the session error string should have been set by the callback. */
126 typedef int (*ne_block_reader
)(void *userdata
, const char *buf
, size_t len
);
128 /* Add a response reader for the given request, with the given
129 * acceptance function. userdata is passed as the first argument to
130 * the acceptance + reader callbacks.
132 * The acceptance callback is called once each time the request is
133 * sent: it may be sent >1 time because of authentication retries etc.
134 * For each time the acceptance callback is called, if it returns
135 * non-zero, blocks of the response body will be passed to the reader
136 * callback as the response is read. After all the response body has
137 * been read, the callback will be called with a 'len' argument of
139 void ne_add_response_body_reader(ne_request
*req
, ne_accept_response accpt
,
140 ne_block_reader reader
, void *userdata
);
142 /* Retrieve the value of the response header field with given name;
143 * returns NULL if no response header with given name was found. The
144 * return value is valid only until the next call to either
145 * ne_request_destroy or ne_begin_request for this request. */
146 const char *ne_get_response_header(ne_request
*req
, const char *name
);
148 /* Iterator interface for response headers: if passed a NULL cursor,
149 * returns the first header; if passed a non-NULL cursor pointer,
150 * returns the next header. The return value is a cursor pointer: if
151 * it is non-NULL, *name and *value are set to the name and value of
152 * the header field. If the return value is NULL, no more headers are
153 * found, *name and *value are undefined.
155 * The order in which response headers is returned is undefined. Both
156 * the cursor and name/value pointers are valid only until the next
157 * call to either ne_request_destroy or ne_begin_request for this
159 void *ne_response_header_iterate(ne_request
*req
, void *cursor
,
160 const char **name
, const char **value
);
162 /* Adds a header to the request with given name and value. */
163 void ne_add_request_header(ne_request
*req
, const char *name
,
165 /* Adds a header to the request with given name, using printf-like
166 * format arguments for the value. */
167 void ne_print_request_header(ne_request
*req
, const char *name
,
168 const char *format
, ...)
169 ne_attribute((format(printf
, 3, 4)));
171 /* ne_request_dispatch: Sends the given request, and reads the
173 * - NE_OK if the request was sent and response read successfully
174 * - NE_AUTH, NE_PROXYAUTH for a server or proxy server authentication error
175 * - NE_CONNECT if connection could not be established
176 * - NE_TIMEOUT if an timeout occurred sending or reading from the server
177 * - NE_ERROR for other fatal dispatch errors
178 * On any error, the session error string is set. On success or
179 * authentication error, the actual response-status can be retrieved using
180 * ne_get_status(). */
181 int ne_request_dispatch(ne_request
*req
);
183 /* Returns a pointer to the response status information for the given
184 * request; pointer is valid until request object is destroyed. */
185 const ne_status
*ne_get_status(const ne_request
*req
) ne_attribute((const));
187 /* Returns pointer to session associated with request. */
188 ne_session
*ne_get_session(const ne_request
*req
) ne_attribute((const));
190 /* Destroy memory associated with request pointer */
191 void ne_request_destroy(ne_request
*req
);
193 /* "Caller-pulls" request interface. This is an ALTERNATIVE interface
194 * to ne_request_dispatch: either use that, or do all this yourself:
197 * 1. ne_begin_request (fail if returns non-NE_OK)
198 * 2. while(ne_read_response_block(...) > 0) ... loop ...;
199 * (fail if ne_read_response_block returns <0)
202 * ne_end_request and ne_begin_request both return an NE_* code; if
203 * ne_end_request returns NE_RETRY, you must restart the loop from (1)
205 int ne_begin_request(ne_request
*req
);
206 int ne_end_request(ne_request
*req
);
208 /* Read a block of the response into the passed buffer of size 'buflen'.
211 * <0 - error, stop reading.
212 * 0 - end of response
213 * >0 - number of bytes read into buffer.
215 ssize_t
ne_read_response_block(ne_request
*req
, char *buffer
, size_t buflen
);
217 /* Read response blocks until end of response; exactly equivalent to
218 * calling ne_read_response_block() until it returns 0. Returns
219 * non-zero on error. */
220 int ne_discard_response(ne_request
*req
);
222 /* Read response blocks until end of response, writing content to the
223 * given file descriptor. Returns NE_ERROR on error. */
224 int ne_read_response_to_fd(ne_request
*req
, int fd
);
226 /* If 'flag' is non-zer, enable the HTTP/1.1 "Expect: 100-continue"
227 * feature for the request, which allows the server to send an error
228 * response before the request body is sent. This should only be used
229 * if the server is known to support the feature (not all HTTP/1.1
230 * servers do); the request will time out and fail otherwise. */
231 void ne_set_request_expect100(ne_request
*req
, int flag
);
233 /**** Request hooks handling *****/
235 typedef void (*ne_free_hooks
)(void *cookie
);
237 /* Hook called when a create is created; passed the request method,
238 * and the string used as the Request-URI (which may be an abs_path,
239 * or an absoluteURI, depending on whether an HTTP proxy is in
241 typedef void (*ne_create_request_fn
)(ne_request
*req
, void *userdata
,
242 const char *method
, const char *requri
);
243 void ne_hook_create_request(ne_session
*sess
,
244 ne_create_request_fn fn
, void *userdata
);
246 /* Hook called before the request is sent. 'header' is the raw HTTP
247 * header before the trailing CRLF is added: add in more here. */
248 typedef void (*ne_pre_send_fn
)(ne_request
*req
, void *userdata
,
250 void ne_hook_pre_send(ne_session
*sess
, ne_pre_send_fn fn
, void *userdata
);
252 /* Hook called after the request is dispatched (request sent, and
253 * the entire response read). If an error occurred reading the response,
254 * this hook will not run. May return:
255 * NE_OK everything is okay
256 * NE_RETRY try sending the request again.
257 * anything else signifies an error, and the request is failed. The return
258 * code is passed back the _dispatch caller, so the session error must
259 * also be set appropriately (ne_set_error).
261 typedef int (*ne_post_send_fn
)(ne_request
*req
, void *userdata
,
262 const ne_status
*status
);
263 void ne_hook_post_send(ne_session
*sess
, ne_post_send_fn fn
, void *userdata
);
265 /* Hook called when the function is destroyed. */
266 typedef void (*ne_destroy_req_fn
)(ne_request
*req
, void *userdata
);
267 void ne_hook_destroy_request(ne_session
*sess
,
268 ne_destroy_req_fn fn
, void *userdata
);
270 typedef void (*ne_destroy_sess_fn
)(void *userdata
);
271 /* Hook called when the session is destroyed. */
272 void ne_hook_destroy_session(ne_session
*sess
,
273 ne_destroy_sess_fn fn
, void *userdata
);
275 /* Store an opaque context for the request, 'priv' is returned by a
276 * call to ne_request_get_private with the same ID. */
277 void ne_set_request_private(ne_request
*req
, const char *id
, void *priv
);
278 void *ne_get_request_private(ne_request
*req
, const char *id
);
282 #endif /* NE_REQUEST_H */