1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * soup-status.c: Status code descriptions
4 *
5 * Copyright (C) 2001-2003, Ximian, Inc.
6 */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include "soup-status.h"
13 #include "soup.h"
14
15 /**
16 * SECTION:soup-status
17 * @short_description: HTTP (and libsoup) status codes
18 *
19 **/
20
21 /**
22 * SOUP_STATUS_IS_TRANSPORT_ERROR:
23 * @status: a status code
24 *
25 * Tests if @status is a libsoup transport error.
26 *
27 * Return value: %TRUE or %FALSE
28 **/
29 /**
30 * SOUP_STATUS_IS_INFORMATIONAL:
31 * @status: an HTTP status code
32 *
33 * Tests if @status is an Informational (1xx) response.
34 *
35 * Return value: %TRUE or %FALSE
36 **/
37 /**
38 * SOUP_STATUS_IS_SUCCESSFUL:
39 * @status: an HTTP status code
40 *
41 * Tests if @status is a Successful (2xx) response.
42 *
43 * Return value: %TRUE or %FALSE
44 **/
45 /**
46 * SOUP_STATUS_IS_REDIRECTION:
47 * @status: an HTTP status code
48 *
49 * Tests if @status is a Redirection (3xx) response.
50 *
51 * Return value: %TRUE or %FALSE
52 **/
53 /**
54 * SOUP_STATUS_IS_CLIENT_ERROR:
55 * @status: an HTTP status code
56 *
57 * Tests if @status is a Client Error (4xx) response.
58 *
59 * Return value: %TRUE or %FALSE
60 **/
61 /**
62 * SOUP_STATUS_IS_SERVER_ERROR:
63 * @status: an HTTP status code
64 *
65 * Tests if @status is a Server Error (5xx) response.
66 *
67 * Return value: %TRUE or %FALSE
68 **/
69
70 /**
71 * SoupStatus:
72 * @SOUP_STATUS_NONE: No status available. (Eg, the message has not
73 * been sent yet)
74 * @SOUP_STATUS_CANCELLED: Message was cancelled locally
75 * @SOUP_STATUS_CANT_RESOLVE: Unable to resolve destination host name
76 * @SOUP_STATUS_CANT_RESOLVE_PROXY: Unable to resolve proxy host name
77 * @SOUP_STATUS_CANT_CONNECT: Unable to connect to remote host
78 * @SOUP_STATUS_CANT_CONNECT_PROXY: Unable to connect to proxy
79 * @SOUP_STATUS_SSL_FAILED: SSL/TLS negotiation failed
80 * @SOUP_STATUS_IO_ERROR: A network error occurred, or the other end
81 * closed the connection unexpectedly
82 * @SOUP_STATUS_MALFORMED: Malformed data (usually a programmer error)
83 * @SOUP_STATUS_TRY_AGAIN: Used internally
84 * @SOUP_STATUS_TOO_MANY_REDIRECTS: There were too many redirections
85 * @SOUP_STATUS_TLS_FAILED: Used internally
86 * @SOUP_STATUS_CONTINUE: 100 Continue (HTTP)
87 * @SOUP_STATUS_SWITCHING_PROTOCOLS: 101 Switching Protocols (HTTP)
88 * @SOUP_STATUS_PROCESSING: 102 Processing (WebDAV)
89 * @SOUP_STATUS_OK: 200 Success (HTTP). Also used by many lower-level
90 * soup routines to indicate success.
91 * @SOUP_STATUS_CREATED: 201 Created (HTTP)
92 * @SOUP_STATUS_ACCEPTED: 202 Accepted (HTTP)
93 * @SOUP_STATUS_NON_AUTHORITATIVE: 203 Non-Authoritative Information
94 * (HTTP)
95 * @SOUP_STATUS_NO_CONTENT: 204 No Content (HTTP)
96 * @SOUP_STATUS_RESET_CONTENT: 205 Reset Content (HTTP)
97 * @SOUP_STATUS_PARTIAL_CONTENT: 206 Partial Content (HTTP)
98 * @SOUP_STATUS_MULTI_STATUS: 207 Multi-Status (WebDAV)
99 * @SOUP_STATUS_MULTIPLE_CHOICES: 300 Multiple Choices (HTTP)
100 * @SOUP_STATUS_MOVED_PERMANENTLY: 301 Moved Permanently (HTTP)
101 * @SOUP_STATUS_FOUND: 302 Found (HTTP)
102 * @SOUP_STATUS_MOVED_TEMPORARILY: 302 Moved Temporarily (old name,
103 * RFC 2068)
104 * @SOUP_STATUS_SEE_OTHER: 303 See Other (HTTP)
105 * @SOUP_STATUS_NOT_MODIFIED: 304 Not Modified (HTTP)
106 * @SOUP_STATUS_USE_PROXY: 305 Use Proxy (HTTP)
107 * @SOUP_STATUS_NOT_APPEARING_IN_THIS_PROTOCOL: 306 [Unused] (HTTP)
108 * @SOUP_STATUS_TEMPORARY_REDIRECT: 307 Temporary Redirect (HTTP)
109 * @SOUP_STATUS_BAD_REQUEST: 400 Bad Request (HTTP)
110 * @SOUP_STATUS_UNAUTHORIZED: 401 Unauthorized (HTTP)
111 * @SOUP_STATUS_PAYMENT_REQUIRED: 402 Payment Required (HTTP)
112 * @SOUP_STATUS_FORBIDDEN: 403 Forbidden (HTTP)
113 * @SOUP_STATUS_NOT_FOUND: 404 Not Found (HTTP)
114 * @SOUP_STATUS_METHOD_NOT_ALLOWED: 405 Method Not Allowed (HTTP)
115 * @SOUP_STATUS_NOT_ACCEPTABLE: 406 Not Acceptable (HTTP)
116 * @SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED: 407 Proxy Authentication
117 * Required (HTTP)
118 * @SOUP_STATUS_PROXY_UNAUTHORIZED: shorter alias for
119 * %SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED
120 * @SOUP_STATUS_REQUEST_TIMEOUT: 408 Request Timeout (HTTP)
121 * @SOUP_STATUS_CONFLICT: 409 Conflict (HTTP)
122 * @SOUP_STATUS_GONE: 410 Gone (HTTP)
123 * @SOUP_STATUS_LENGTH_REQUIRED: 411 Length Required (HTTP)
124 * @SOUP_STATUS_PRECONDITION_FAILED: 412 Precondition Failed (HTTP)
125 * @SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE: 413 Request Entity Too Large
126 * (HTTP)
127 * @SOUP_STATUS_REQUEST_URI_TOO_LONG: 414 Request-URI Too Long (HTTP)
128 * @SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE: 415 Unsupported Media Type
129 * (HTTP)
130 * @SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE: 416 Requested Range
131 * Not Satisfiable (HTTP)
132 * @SOUP_STATUS_INVALID_RANGE: shorter alias for
133 * %SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE
134 * @SOUP_STATUS_EXPECTATION_FAILED: 417 Expectation Failed (HTTP)
135 * @SOUP_STATUS_UNPROCESSABLE_ENTITY: 422 Unprocessable Entity
136 * (WebDAV)
137 * @SOUP_STATUS_LOCKED: 423 Locked (WebDAV)
138 * @SOUP_STATUS_FAILED_DEPENDENCY: 424 Failed Dependency (WebDAV)
139 * @SOUP_STATUS_INTERNAL_SERVER_ERROR: 500 Internal Server Error
140 * (HTTP)
141 * @SOUP_STATUS_NOT_IMPLEMENTED: 501 Not Implemented (HTTP)
142 * @SOUP_STATUS_BAD_GATEWAY: 502 Bad Gateway (HTTP)
143 * @SOUP_STATUS_SERVICE_UNAVAILABLE: 503 Service Unavailable (HTTP)
144 * @SOUP_STATUS_GATEWAY_TIMEOUT: 504 Gateway Timeout (HTTP)
145 * @SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED: 505 HTTP Version Not
146 * Supported (HTTP)
147 * @SOUP_STATUS_INSUFFICIENT_STORAGE: 507 Insufficient Storage
148 * (WebDAV)
149 * @SOUP_STATUS_NOT_EXTENDED: 510 Not Extended (RFC 2774)
150 *
151 * These represent the known HTTP status code values, plus various
152 * network and internal errors.
153 *
154 * Note that no libsoup functions take or return this type directly;
155 * any function that works with status codes will accept unrecognized
156 * status codes as well.
157 *
158 * Prior to 2.44 this type was called
159 * <literal>SoupKnownStatusCode</literal>, but the individual values
160 * have always had the names they have now.
161 **/
162
163 /* The reason_phrases are not localized because:
164 *
165 * 1. Only ASCII can be used portably in the HTTP Status-Line, so we
166 * would not be able to return localized reason phrases from
167 * SoupServer anyway.
168 *
169 * 2. Having a way for clients to get a localized version of a status
170 * code would just encourage them to present those strings to the
171 * user, which is bad because many of them are fairly
172 * incomprehensible anyway.
173 */
174
175 static const struct {
176 guint code;
177 const char *phrase;
178 } reason_phrases [] = {
179 /* Transport errors */
180 { SOUP_STATUS_CANCELLED, "Cancelled" },
181 { SOUP_STATUS_CANT_RESOLVE, "Cannot resolve hostname" },
182 { SOUP_STATUS_CANT_RESOLVE_PROXY, "Cannot resolve proxy hostname" },
183 { SOUP_STATUS_CANT_CONNECT, "Cannot connect to destination" },
184 { SOUP_STATUS_CANT_CONNECT_PROXY, "Cannot connect to proxy" },
185 { SOUP_STATUS_SSL_FAILED, "SSL handshake failed" },
186 { SOUP_STATUS_IO_ERROR, "Connection terminated unexpectedly" },
187 { SOUP_STATUS_MALFORMED, "Message Corrupt" },
188 { SOUP_STATUS_TOO_MANY_REDIRECTS, "Too many redirects" },
189
190 /* Informational */
191 { SOUP_STATUS_CONTINUE, "Continue" },
192 { SOUP_STATUS_SWITCHING_PROTOCOLS, "Switching Protocols" },
193 { SOUP_STATUS_PROCESSING, "Processing" },
194
195 /* Success */
196 { SOUP_STATUS_OK, "OK" },
197 { SOUP_STATUS_CREATED, "Created" },
198 { SOUP_STATUS_ACCEPTED, "Accepted" },
199 { SOUP_STATUS_NON_AUTHORITATIVE, "Non-Authoritative Information" },
200 { SOUP_STATUS_NO_CONTENT, "No Content" },
201 { SOUP_STATUS_RESET_CONTENT, "Reset Content" },
202 { SOUP_STATUS_PARTIAL_CONTENT, "Partial Content" },
203 { SOUP_STATUS_MULTI_STATUS, "Multi-Status" },
204
205 /* Redirection */
206 { SOUP_STATUS_MULTIPLE_CHOICES, "Multiple Choices" },
207 { SOUP_STATUS_MOVED_PERMANENTLY, "Moved Permanently" },
208 { SOUP_STATUS_FOUND, "Found" },
209 { SOUP_STATUS_SEE_OTHER, "See Other" },
210 { SOUP_STATUS_NOT_MODIFIED, "Not Modified" },
211 { SOUP_STATUS_USE_PROXY, "Use Proxy" },
212 { SOUP_STATUS_TEMPORARY_REDIRECT, "Temporary Redirect" },
213
214 /* Client error */
215 { SOUP_STATUS_BAD_REQUEST, "Bad Request" },
216 { SOUP_STATUS_UNAUTHORIZED, "Unauthorized" },
217 { SOUP_STATUS_PAYMENT_REQUIRED, "Payment Required" },
218 { SOUP_STATUS_FORBIDDEN, "Forbidden" },
219 { SOUP_STATUS_NOT_FOUND, "Not Found" },
220 { SOUP_STATUS_METHOD_NOT_ALLOWED, "Method Not Allowed" },
221 { SOUP_STATUS_NOT_ACCEPTABLE, "Not Acceptable" },
222 { SOUP_STATUS_PROXY_UNAUTHORIZED, "Proxy Authentication Required" },
223 { SOUP_STATUS_REQUEST_TIMEOUT, "Request Timeout" },
224 { SOUP_STATUS_CONFLICT, "Conflict" },
225 { SOUP_STATUS_GONE, "Gone" },
226 { SOUP_STATUS_LENGTH_REQUIRED, "Length Required" },
227 { SOUP_STATUS_PRECONDITION_FAILED, "Precondition Failed" },
228 { SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE, "Request Entity Too Large" },
229 { SOUP_STATUS_REQUEST_URI_TOO_LONG, "Request-URI Too Long" },
230 { SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type" },
231 { SOUP_STATUS_INVALID_RANGE, "Requested Range Not Satisfiable" },
232 { SOUP_STATUS_EXPECTATION_FAILED, "Expectation Failed" },
233 { SOUP_STATUS_UNPROCESSABLE_ENTITY, "Unprocessable Entity" },
234 { SOUP_STATUS_LOCKED, "Locked" },
235 { SOUP_STATUS_FAILED_DEPENDENCY, "Failed Dependency" },
236
237 /* Server error */
238 { SOUP_STATUS_INTERNAL_SERVER_ERROR, "Internal Server Error" },
239 { SOUP_STATUS_NOT_IMPLEMENTED, "Not Implemented" },
240 { SOUP_STATUS_BAD_GATEWAY, "Bad Gateway" },
241 { SOUP_STATUS_SERVICE_UNAVAILABLE, "Service Unavailable" },
242 { SOUP_STATUS_GATEWAY_TIMEOUT, "Gateway Timeout" },
243 { SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported" },
244 { SOUP_STATUS_INSUFFICIENT_STORAGE, "Insufficient Storage" },
245 { SOUP_STATUS_NOT_EXTENDED, "Not Extended" },
246
247 { 0 }
248 };
249
250 /**
251 * soup_status_get_phrase:
252 * @status_code: an HTTP status code
253 *
254 * Looks up the stock HTTP description of @status_code. This is used
255 * by soup_message_set_status() to get the correct text to go with a
256 * given status code.
257 *
258 * <emphasis>There is no reason for you to ever use this
259 * function.</emphasis> If you wanted the textual description for the
260 * #SoupMessage:status_code of a given #SoupMessage, you should just
261 * look at the message's #SoupMessage:reason_phrase. However, you
262 * should only do that for use in debugging messages; HTTP reason
263 * phrases are not localized, and are not generally very descriptive
264 * anyway, and so they should never be presented to the user directly.
265 * Instead, you should create you own error messages based on the
266 * status code, and on what you were trying to do.
267 *
268 * Return value: the (terse, English) description of @status_code
269 **/
270 const char *
soup_status_get_phrase(guint status_code)271 soup_status_get_phrase (guint status_code)
272 {
273 int i;
274
275 for (i = 0; reason_phrases [i].code; i++) {
276 if (reason_phrases [i].code == status_code)
277 return reason_phrases [i].phrase;
278 }
279
280 return "Unknown Error";
281 }
282
283 /**
284 * soup_status_proxify:
285 * @status_code: a status code
286 *
287 * Turns %SOUP_STATUS_CANT_RESOLVE into
288 * %SOUP_STATUS_CANT_RESOLVE_PROXY and %SOUP_STATUS_CANT_CONNECT into
289 * %SOUP_STATUS_CANT_CONNECT_PROXY. Other status codes are passed
290 * through unchanged.
291 *
292 * Return value: the "proxified" equivalent of @status_code.
293 *
294 * Since: 2.26
295 **/
296 guint
soup_status_proxify(guint status_code)297 soup_status_proxify (guint status_code)
298 {
299 if (status_code == SOUP_STATUS_CANT_RESOLVE)
300 return SOUP_STATUS_CANT_RESOLVE_PROXY;
301 else if (status_code == SOUP_STATUS_CANT_CONNECT)
302 return SOUP_STATUS_CANT_CONNECT_PROXY;
303 else
304 return status_code;
305 }
306
307 G_DEFINE_QUARK (soup-http-error-quark, soup_http_error)
308