aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/c
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adamc@hcoop.net>2009-12-10 13:32:09 -0500
committerGravatar Adam Chlipala <adamc@hcoop.net>2009-12-10 13:32:09 -0500
commitb04e123d0e1159d431aae00c3e8f1cc4a1b95684 (patch)
tree0f8fb3c5e3f1278843704633e53f27ec20e49b06 /src/c
parent14163f6e6e160694eff3d409ca3cf0b8b76c4a3a (diff)
Basis.url and redirects
Diffstat (limited to 'src/c')
-rw-r--r--src/c/request.c2
-rw-r--r--src/c/urweb.c46
2 files changed, 41 insertions, 7 deletions
diff --git a/src/c/request.c b/src/c/request.c
index 069de4aa..2357a86b 100644
--- a/src/c/request.c
+++ b/src/c/request.c
@@ -374,7 +374,7 @@ request_result uw_request(uw_request_context rc, uw_context ctx,
}
strcpy(rc->path_copy, path);
fk = uw_begin(ctx, rc->path_copy);
- if (fk == SUCCESS || fk == RETURN_BLOB) {
+ if (fk == SUCCESS || fk == RETURN_INDIRECTLY) {
uw_commit(ctx);
return SERVED;
} else if (fk == BOUNDED_RETRY) {
diff --git a/src/c/urweb.c b/src/c/urweb.c
index 95142a2d..476e3794 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -199,6 +199,7 @@ static client *find_client(unsigned id) {
}
static char *on_success = "HTTP/1.1 200 OK\r\n";
+static char *on_redirect = "HTTP/1.1 303 See Other\r\n";
void uw_set_on_success(char *s) {
on_success = s;
@@ -352,7 +353,7 @@ struct uw_context {
void *get_header_data;
buf outHeaders, page, heap, script;
- int returning_blob;
+ int returning_indirectly;
input *inputs, *subinputs, *cur_container;
size_t n_subinputs, used_subinputs;
@@ -396,7 +397,7 @@ uw_context uw_init() {
buf_init(&ctx->outHeaders, 0);
buf_init(&ctx->page, 0);
- ctx->returning_blob = 0;
+ ctx->returning_indirectly = 0;
buf_init(&ctx->heap, 0);
buf_init(&ctx->script, 1);
ctx->script.start[0] = 0;
@@ -475,7 +476,7 @@ void uw_reset_keep_error_message(uw_context ctx) {
buf_reset(&ctx->script);
ctx->script.start[0] = 0;
buf_reset(&ctx->page);
- ctx->returning_blob = 0;
+ ctx->returning_indirectly = 0;
buf_reset(&ctx->heap);
ctx->regions = NULL;
ctx->cleanup_front = ctx->cleanup;
@@ -2793,7 +2794,7 @@ void uw_commit(uw_context ctx) {
ctx->transactionals[i].free(ctx->transactionals[i].data);
// Splice script data into appropriate part of page
- if (ctx->returning_blob || ctx->script_header[0] == 0) {
+ if (ctx->returning_indirectly || ctx->script_header[0] == 0) {
char *start = strstr(ctx->page.start, "<sc>");
if (start) {
memmove(start, start + 4, buf_used(&ctx->page) - (start - ctx->page.start) - 4);
@@ -2942,7 +2943,17 @@ failure_kind uw_initialize(uw_context ctx) {
extern int uw_check_url(const char *);
extern int uw_check_mime(const char *);
+static int url_bad(uw_Basis_string s) {
+ for (; *s; ++s)
+ if (!isgraph(*s))
+ return 1;
+
+ return 0;
+}
+
uw_Basis_string uw_Basis_bless(uw_context ctx, uw_Basis_string s) {
+ if (url_bad(s))
+ uw_error(ctx, FATAL, "Invalid URL %s", uw_Basis_htmlifyString(ctx, s));
if (uw_check_url(s))
return s;
else
@@ -2950,6 +2961,8 @@ uw_Basis_string uw_Basis_bless(uw_context ctx, uw_Basis_string s) {
}
uw_Basis_string uw_Basis_checkUrl(uw_context ctx, uw_Basis_string s) {
+ if (url_bad(s))
+ return NULL;
if (uw_check_url(s))
return s;
else
@@ -3024,7 +3037,7 @@ __attribute__((noreturn)) void uw_return_blob(uw_context ctx, uw_Basis_blob b, u
cleanup *cl;
int len;
- ctx->returning_blob = 1;
+ ctx->returning_indirectly = 1;
buf_reset(&ctx->outHeaders);
buf_reset(&ctx->page);
@@ -3044,7 +3057,28 @@ __attribute__((noreturn)) void uw_return_blob(uw_context ctx, uw_Basis_blob b, u
ctx->cleanup_front = ctx->cleanup;
- longjmp(ctx->jmp_buf, RETURN_BLOB);
+ longjmp(ctx->jmp_buf, RETURN_INDIRECTLY);
+}
+
+__attribute__((noreturn)) void uw_redirect(uw_context ctx, uw_Basis_string url) {
+ cleanup *cl;
+ int len;
+
+ ctx->returning_indirectly = 1;
+ buf_reset(&ctx->outHeaders);
+ buf_reset(&ctx->page);
+
+ uw_write_header(ctx, on_redirect);
+ uw_write_header(ctx, "Location: ");
+ uw_write_header(ctx, url);
+ uw_write_header(ctx, "\r\n\r\n");
+
+ for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl)
+ cl->func(cl->arg);
+
+ ctx->cleanup_front = ctx->cleanup;
+
+ longjmp(ctx->jmp_buf, RETURN_INDIRECTLY);
}
uw_Basis_string uw_Basis_unAs(uw_context ctx, uw_Basis_string s) {