2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #include "private-libwebsockets.h"
23 #include "lextable-strings.h"
25 const unsigned char *lws_token_to_string(enum lws_token_indexes token)
27 if ((unsigned int)token >= ARRAY_SIZE(set))
29 return (unsigned char *)set[token];
32 int lws_add_http_header_by_name(struct libwebsocket_context *context,
33 struct libwebsocket *wsi,
34 const unsigned char *name,
35 const unsigned char *value,
41 if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
42 return lws_add_http2_header_by_name(context, wsi, name, value, length, p, end);
48 while (*p < end && *name)
54 if (*p + length + 3 >= end)
57 memcpy(*p, value, length);
64 int lws_finalize_http_header(struct libwebsocket_context *context,
65 struct libwebsocket *wsi,
71 if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
76 if ((long)(end - *p) < 3)
83 int lws_add_http_header_by_token(struct libwebsocket_context *context,
84 struct libwebsocket *wsi,
85 enum lws_token_indexes token,
86 const unsigned char *value,
91 const unsigned char *name;
93 if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
94 return lws_add_http2_header_by_token(context, wsi, token, value, length, p, end);
96 name = lws_token_to_string(token);
99 return lws_add_http_header_by_name(context, wsi, name, value, length, p, end);
102 int lws_add_http_header_content_length(struct libwebsocket_context *context,
103 struct libwebsocket *wsi,
104 unsigned long content_length,
111 n = sprintf(b, "%lu", content_length);
112 if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, (unsigned char *)b, n, p, end))
114 wsi->u.http.content_length = content_length;
115 wsi->u.http.content_remain = content_length;
120 static const char *err400[] = {
126 "Method Not Allowed",
128 "Proxy Auth Required",
133 "Precondition Failed",
134 "Request Entity Too Large",
135 "Request URI too Long",
136 "Unsupported Media Type",
137 "Requested Range Not Satisfiable",
141 static const char *err500[] = {
142 "Internal Server Error",
145 "Service Unavailable",
147 "HTTP Version Not Supported"
150 int lws_add_http_header_status(struct libwebsocket_context *context,
151 struct libwebsocket *wsi,
156 unsigned char code_and_desc[60];
157 const char *description = "";
161 if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
162 return lws_add_http2_header_status(context, wsi, code, p, end);
164 if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
165 description = err400[code - 400];
166 if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
167 description = err500[code - 500];
169 n = sprintf((char *)code_and_desc, "HTTP/1.0 %u %s", code, description);
171 return lws_add_http_header_by_name(context, wsi, NULL, code_and_desc, n, p, end);
175 * lws_return_http_status() - Return simple http status
176 * @context: libwebsockets context
177 * @wsi: Websocket instance (available from user callback)
178 * @code: Status index, eg, 404
179 * @html_body: User-readable HTML description < 1KB, or NULL
181 * Helper to report HTTP errors back to the client cleanly and
184 LWS_VISIBLE int lws_return_http_status(
185 struct libwebsocket_context *context, struct libwebsocket *wsi,
186 unsigned int code, const char *html_body)
190 unsigned char *p = context->service_buffer + LWS_SEND_BUFFER_PRE_PADDING;
191 unsigned char *start = p;
192 unsigned char *end = p + sizeof(context->service_buffer) -
193 LWS_SEND_BUFFER_PRE_PADDING;
198 if (lws_add_http_header_status(context, wsi, code, &p, end))
200 if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_SERVER, (unsigned char *)"libwebsockets", 13, &p, end))
202 if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"text/html", 9, &p, end))
204 if (lws_finalize_http_header(context, wsi, &p, end))
207 m = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
208 if (m != (int)(p - start))
211 n = sprintf((char *)start, "<html><body><h1>%u</h1>%s</body></html>", code, html_body);
212 m = lws_write(wsi, start, n, LWS_WRITE_HTTP);