Commit 460d95af authored by Deomid Ryabkov's avatar Deomid Ryabkov Committed by Cesanta Bot

Add mg_http_send_redirect and make examples use it

PUBLISHED_FROM=f45e06aeba1c00212078d539b6f74cb8bd054326
parent 8f522048
...@@ -16,6 +16,7 @@ items: ...@@ -16,6 +16,7 @@ items:
- { name: mg_send_http_chunk.md } - { name: mg_send_http_chunk.md }
- { name: mg_printf_http_chunk.md } - { name: mg_printf_http_chunk.md }
- { name: mg_send_response_line.md } - { name: mg_send_response_line.md }
- { name: mg_http_send_redirect.md }
- { name: mg_send_head.md } - { name: mg_send_head.md }
- { name: mg_printf_html_escape.md } - { name: mg_printf_html_escape.md }
- { name: mg_fu_fname_fn.md } - { name: mg_fu_fname_fn.md }
......
---
title: "mg_http_send_redirect()"
decl_name: "mg_http_send_redirect"
symbol_kind: "func"
signature: |
void mg_http_send_redirect(struct mg_connection *nc, int status_code,
const struct mg_str location,
const struct mg_str extra_headers);
---
Sends a redirect response.
`status_code` should be either 301 or 302 and `location` point to the
new location.
If `extra_headers` is not empty, then `extra_headers` are also sent
after the reponse line. `extra_headers` must NOT end end with new line.
Example:
mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
Will result in:
HTTP/1.1 200 OK\r\n
Access-Control-Allow-Origin: *\r\n
...@@ -3,7 +3,7 @@ title: "mg_send_response_line()" ...@@ -3,7 +3,7 @@ title: "mg_send_response_line()"
decl_name: "mg_send_response_line" decl_name: "mg_send_response_line"
symbol_kind: "func" symbol_kind: "func"
signature: | signature: |
void mg_send_response_line(struct mg_connection *c, int status_code, void mg_send_response_line(struct mg_connection *nc, int status_code,
const char *extra_headers); const char *extra_headers);
--- ---
......
...@@ -17,6 +17,7 @@ items: ...@@ -17,6 +17,7 @@ items:
- { name: mg_sock_addr_to_str.md } - { name: mg_sock_addr_to_str.md }
- { name: mg_hexdump.md } - { name: mg_hexdump.md }
- { name: mg_hexdump_connection.md } - { name: mg_hexdump_connection.md }
- { name: mg_asprintf.md }
- { name: mg_avprintf.md } - { name: mg_avprintf.md }
- { name: mg_is_big_endian.md } - { name: mg_is_big_endian.md }
- { name: mg_next_comma_list_entry.md } - { name: mg_next_comma_list_entry.md }
......
---
title: "mg_asprintf()"
decl_name: "mg_asprintf"
symbol_kind: "func"
signature: |
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
---
Prints message to the buffer. If the buffer is large enough to hold the
message, it returns buffer. If buffer is to small, it allocates a large
enough buffer on heap and returns allocated buffer.
This is a supposed use case:
char buf[5], *p = buf;
mg_avprintf(&p, sizeof(buf), "%s", "hi there");
use_p_somehow(p);
if (p != buf) {
free(p);
}
The purpose of this is to avoid malloc-ing if generated strings are small.
...@@ -6,17 +6,5 @@ signature: | ...@@ -6,17 +6,5 @@ signature: |
int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap); int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
--- ---
Prints message to the buffer. If the buffer is large enough to hold the Same as mg_asprintf, but takes varargs list.
message, it returns buffer. If buffer is to small, it allocates a large
enough buffer on heap and returns allocated buffer.
This is a supposed use case:
char buf[5], *p = buf;
p = mg_avprintf(&p, sizeof(buf), "%s", "hi there");
use_p_somehow(p);
if (p != buf) {
free(p);
}
The purpose of this is to avoid malloc-ing if generated strings are small.
...@@ -20,7 +20,7 @@ static void handle_save(struct mg_connection *nc, struct http_message *hm) { ...@@ -20,7 +20,7 @@ static void handle_save(struct mg_connection *nc, struct http_message *hm) {
sizeof(s_settings.setting2)); sizeof(s_settings.setting2));
// Send response // Send response
mg_printf(nc, "%s", "HTTP/1.1 302 OK\r\nLocation: /\r\n\r\n"); mg_http_send_redirect(nc, 302, mg_mk_str("/"), mg_mk_str(NULL));
} }
static void handle_ssi_call(struct mg_connection *nc, const char *param) { static void handle_ssi_call(struct mg_connection *nc, const char *param) {
......
...@@ -20,7 +20,7 @@ static void handle_save(struct mg_connection *nc, struct http_message *hm) { ...@@ -20,7 +20,7 @@ static void handle_save(struct mg_connection *nc, struct http_message *hm) {
sizeof(s_settings.setting2)); sizeof(s_settings.setting2));
// Send response // Send response
mg_printf(nc, "%s", "HTTP/1.1 302 OK\r\nLocation: /\r\n\r\n"); mg_http_send_redirect(nc, 302, mg_mk_str("/"), mg_mk_str(NULL));
} }
static void handle_get_cpu_usage(struct mg_connection *nc) { static void handle_get_cpu_usage(struct mg_connection *nc) {
......
...@@ -20,7 +20,7 @@ static void handle_save(struct mg_connection *nc, struct http_message *hm) { ...@@ -20,7 +20,7 @@ static void handle_save(struct mg_connection *nc, struct http_message *hm) {
sizeof(s_settings.setting2)); sizeof(s_settings.setting2));
// Send response // Send response
mg_printf(nc, "%s", "HTTP/1.1 302 OK\r\nLocation: /\r\n\r\n"); mg_http_send_redirect(nc, 302, mg_mk_str("/"), mg_mk_str(NULL));
} }
static void handle_get_cpu_usage(struct mg_connection *nc) { static void handle_get_cpu_usage(struct mg_connection *nc) {
......
...@@ -120,12 +120,6 @@ static struct session *create_session(const char *user, ...@@ -120,12 +120,6 @@ static struct session *create_session(const char *user,
return s; return s;
} }
static void set_session_cookie(struct mg_connection *nc,
const struct session *s) {
mg_printf(nc, "Set-Cookie: %s=%" INT64_X_FMT "; path=/\r\n",
SESSION_COOKIE_NAME, s->id);
}
/* /*
* If requested via GET, serves the login page. * If requested via GET, serves the login page.
* If requested via POST (form submission), checks password and logs user in. * If requested via POST (form submission), checks password and logs user in.
...@@ -143,10 +137,11 @@ static void login_handler(struct mg_connection *nc, int ev, void *p) { ...@@ -143,10 +137,11 @@ static void login_handler(struct mg_connection *nc, int ev, void *p) {
if (ul > 0 && pl > 0) { if (ul > 0 && pl > 0) {
if (check_pass(user, pass)) { if (check_pass(user, pass)) {
struct session *s = create_session(user, hm); struct session *s = create_session(user, hm);
mg_printf(nc, "HTTP/1.0 302 Found\r\n"); char shead[100];
set_session_cookie(nc, s); snprintf(shead, sizeof(shead),
mg_printf(nc, "Location: /\r\n"); "Set-Cookie: %s=%" INT64_X_FMT "; path=/", SESSION_COOKIE_NAME,
mg_printf(nc, "\r\nHello, %s!\r\n", s->user); s->id);
mg_http_send_redirect(nc, 302, mg_mk_str("/"), mg_mk_str(shead));
fprintf(stderr, "%s logged in, sid %" INT64_X_FMT "\n", s->user, s->id); fprintf(stderr, "%s logged in, sid %" INT64_X_FMT "\n", s->user, s->id);
} else { } else {
mg_printf(nc, "HTTP/1.0 403 Unauthorized\r\n\r\nWrong password.\r\n"); mg_printf(nc, "HTTP/1.0 403 Unauthorized\r\n\r\nWrong password.\r\n");
...@@ -165,13 +160,9 @@ static void login_handler(struct mg_connection *nc, int ev, void *p) { ...@@ -165,13 +160,9 @@ static void login_handler(struct mg_connection *nc, int ev, void *p) {
*/ */
static void logout_handler(struct mg_connection *nc, int ev, void *p) { static void logout_handler(struct mg_connection *nc, int ev, void *p) {
struct http_message *hm = (struct http_message *) p; struct http_message *hm = (struct http_message *) p;
mg_printf(nc, char shead[100];
"HTTP/1.0 302 Found\r\n" snprintf(shead, sizeof(shead), "Set-Cookie: %s=", SESSION_COOKIE_NAME);
"Set-Cookie: %s=\r\n" mg_http_send_redirect(nc, 302, mg_mk_str("/"), mg_mk_str(shead));
"Location: /\r\n"
"\r\n"
"Logged out",
SESSION_COOKIE_NAME);
struct session *s = get_session(hm); struct session *s = get_session(hm);
if (s != NULL) { if (s != NULL) {
fprintf(stderr, "%s logged out, session %" INT64_X_FMT " destroyed\n", fprintf(stderr, "%s logged out, session %" INT64_X_FMT " destroyed\n",
...@@ -203,11 +194,8 @@ static void ev_handler(struct mg_connection *nc, int ev, void *p) { ...@@ -203,11 +194,8 @@ static void ev_handler(struct mg_connection *nc, int ev, void *p) {
struct session *s = get_session(hm); struct session *s = get_session(hm);
/* Ask the user to log in if they did not present a valid cookie. */ /* Ask the user to log in if they did not present a valid cookie. */
if (s == NULL) { if (s == NULL) {
mg_printf(nc, mg_http_send_redirect(nc, 302, mg_mk_str("/login.html"),
"HTTP/1.0 302 Found\r\n" mg_mk_str(NULL));
"Location: /login.html\r\n"
"\r\n"
"Please log in");
nc->flags |= MG_F_SEND_AND_CLOSE; nc->flags |= MG_F_SEND_AND_CLOSE;
break; break;
} }
......
...@@ -5336,6 +5336,28 @@ void mg_send_response_line(struct mg_connection *nc, int status_code, ...@@ -5336,6 +5336,28 @@ void mg_send_response_line(struct mg_connection *nc, int status_code,
mg_send_response_line_s(nc, status_code, mg_mk_str(extra_headers)); mg_send_response_line_s(nc, status_code, mg_mk_str(extra_headers));
} }
void mg_http_send_redirect(struct mg_connection *nc, int status_code,
const struct mg_str location,
const struct mg_str extra_headers) {
char bbody[100], *pbody = bbody;
int bl = mg_asprintf(&pbody, sizeof(bbody),
"<p>Moved <a href='%.*s'>here</a>.\r\n",
(int) location.len, location.p);
char bhead[150], *phead = bhead;
mg_asprintf(&phead, sizeof(bhead),
"Location: %.*s\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %d\r\n"
"Cache-Control: no-cache\r\n"
"%.*s%s",
(int) location.len, location.p, bl, (int) extra_headers.len,
extra_headers.p, (extra_headers.len > 0 ? "\r\n" : ""));
mg_send_response_line(nc, status_code, phead);
if (phead != bhead) MG_FREE(phead);
mg_send(nc, pbody, bl);
if (pbody != bbody) MG_FREE(pbody);
}
void mg_send_head(struct mg_connection *c, int status_code, void mg_send_head(struct mg_connection *c, int status_code,
int64_t content_length, const char *extra_headers) { int64_t content_length, const char *extra_headers) {
mg_send_response_line(c, status_code, extra_headers); mg_send_response_line(c, status_code, extra_headers);
...@@ -7754,6 +7776,15 @@ int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap) { ...@@ -7754,6 +7776,15 @@ int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap) {
return len; return len;
} }
int mg_asprintf(char **buf, size_t size, const char *fmt, ...) {
int ret;
va_list ap;
va_start(ap, fmt);
ret = mg_avprintf(buf, size, fmt, ap);
va_end(ap);
return ret;
}
#if !defined(MG_DISABLE_HEXDUMP) #if !defined(MG_DISABLE_HEXDUMP)
void mg_hexdump_connection(struct mg_connection *nc, const char *path, void mg_hexdump_connection(struct mg_connection *nc, const char *path,
const void *buf, int num_bytes, int ev) { const void *buf, int num_bytes, int ev) {
......
...@@ -2009,6 +2009,7 @@ int mg_hexdump(const void *buf, int len, char *dst, int dst_len); ...@@ -2009,6 +2009,7 @@ int mg_hexdump(const void *buf, int len, char *dst, int dst_len);
*/ */
void mg_hexdump_connection(struct mg_connection *nc, const char *path, void mg_hexdump_connection(struct mg_connection *nc, const char *path,
const void *buf, int num_bytes, int ev); const void *buf, int num_bytes, int ev);
/* /*
* Prints message to the buffer. If the buffer is large enough to hold the * Prints message to the buffer. If the buffer is large enough to hold the
* message, it returns buffer. If buffer is to small, it allocates a large * message, it returns buffer. If buffer is to small, it allocates a large
...@@ -2016,7 +2017,7 @@ void mg_hexdump_connection(struct mg_connection *nc, const char *path, ...@@ -2016,7 +2017,7 @@ void mg_hexdump_connection(struct mg_connection *nc, const char *path,
* This is a supposed use case: * This is a supposed use case:
* *
* char buf[5], *p = buf; * char buf[5], *p = buf;
* p = mg_avprintf(&p, sizeof(buf), "%s", "hi there"); * mg_avprintf(&p, sizeof(buf), "%s", "hi there");
* use_p_somehow(p); * use_p_somehow(p);
* if (p != buf) { * if (p != buf) {
* free(p); * free(p);
...@@ -2024,6 +2025,9 @@ void mg_hexdump_connection(struct mg_connection *nc, const char *path, ...@@ -2024,6 +2025,9 @@ void mg_hexdump_connection(struct mg_connection *nc, const char *path,
* *
* The purpose of this is to avoid malloc-ing if generated strings are small. * The purpose of this is to avoid malloc-ing if generated strings are small.
*/ */
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
/* Same as mg_asprintf, but takes varargs list. */
int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap); int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
/* /*
...@@ -2800,9 +2804,28 @@ void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...); ...@@ -2800,9 +2804,28 @@ void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...);
* HTTP/1.1 200 OK\r\n * HTTP/1.1 200 OK\r\n
* Access-Control-Allow-Origin: *\r\n * Access-Control-Allow-Origin: *\r\n
*/ */
void mg_send_response_line(struct mg_connection *c, int status_code, void mg_send_response_line(struct mg_connection *nc, int status_code,
const char *extra_headers); const char *extra_headers);
/*
* Sends a redirect response.
* `status_code` should be either 301 or 302 and `location` point to the
* new location.
* If `extra_headers` is not empty, then `extra_headers` are also sent
* after the reponse line. `extra_headers` must NOT end end with new line.
* Example:
*
* mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
*
* Will result in:
*
* HTTP/1.1 200 OK\r\n
* Access-Control-Allow-Origin: *\r\n
*/
void mg_http_send_redirect(struct mg_connection *nc, int status_code,
const struct mg_str location,
const struct mg_str extra_headers);
/* /*
* Sends the response line and headers. * Sends the response line and headers.
* This function sends the response line with the `status_code`, and * This function sends the response line with the `status_code`, and
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment