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);
45 while (*p < end && *name)
51 if (*p + length + 3 >= end)
54 memcpy(*p, value, length);
61 int lws_finalize_http_header(struct libwebsocket_context *context,
62 struct libwebsocket *wsi,
67 if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
70 if ((long)(end - *p) < 3)
77 int lws_add_http_header_by_token(struct libwebsocket_context *context,
78 struct libwebsocket *wsi,
79 enum lws_token_indexes token,
80 const unsigned char *value,
85 const unsigned char *name;
87 if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
88 return lws_add_http2_header_by_token(context, wsi, token, value, length, p, end);
90 name = lws_token_to_string(token);
93 return lws_add_http_header_by_name(context, wsi, name, value, length, p, end);
96 int lws_add_http_header_content_length(struct libwebsocket_context *context,
97 struct libwebsocket *wsi,
98 unsigned long content_length,
105 n = sprintf(b, "%lu", content_length);
106 if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH, (unsigned char *)b, n, p, end))
108 wsi->u.http.content_length = content_length;
109 wsi->u.http.content_remain = content_length;
114 static const char *err400[] = {
120 "Method Not Allowed",
122 "Proxy Auth Required",
127 "Precondition Failed",
128 "Request Entity Too Large",
129 "Request URI too Long",
130 "Unsupported Media Type",
131 "Requested Range Not Satisfiable",
135 static const char *err500[] = {
136 "Internal Server Error",
139 "Service Unavailable",
141 "HTTP Version Not Supported"
144 int lws_add_http_header_status(struct libwebsocket_context *context,
145 struct libwebsocket *wsi,
150 unsigned char code_and_desc[60];
151 const char *description = "";
155 if (wsi->mode == LWS_CONNMODE_HTTP2_SERVING)
156 return lws_add_http2_header_status(context, wsi, code, p, end);
158 if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
159 description = err400[code - 400];
160 if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
161 description = err500[code - 500];
163 n = sprintf((char *)code_and_desc, "HTTP/1.0 %u %s", code, description);
165 return lws_add_http_header_by_name(context, wsi, NULL, code_and_desc, n, p, end);
169 * libwebsockets_return_http_status() - Return simple http status
170 * @context: libwebsockets context
171 * @wsi: Websocket instance (available from user callback)
172 * @code: Status index, eg, 404
173 * @html_body: User-readable HTML description < 1KB, or NULL
175 * Helper to report HTTP errors back to the client cleanly and
178 LWS_VISIBLE int libwebsockets_return_http_status(
179 struct libwebsocket_context *context, struct libwebsocket *wsi,
180 unsigned int code, const char *html_body)
184 unsigned char *p = context->service_buffer + LWS_SEND_BUFFER_PRE_PADDING;
185 unsigned char *start = p;
186 unsigned char *end = p + sizeof(context->service_buffer) -
187 LWS_SEND_BUFFER_PRE_PADDING;
192 if (lws_add_http_header_status(context, wsi, code, &p, end))
194 if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_SERVER, (unsigned char *)"libwebsockets", 13, &p, end))
196 if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"text/html", 9, &p, end))
198 if (lws_finalize_http_header(context, wsi, &p, end))
201 m = libwebsocket_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
202 if (m != (int)(p - start))
205 n = sprintf((char *)start, "<html><body><h1>%u</h1>%s</body></html>", code, html_body);
206 m = libwebsocket_write(wsi, start, n, LWS_WRITE_HTTP);