Skip to content

Commit 8f50fe6

Browse files
committed
Improve --url-prefix handling with trailing slash normalization and redirect
- Normalize --url-prefix by stripping trailing slashes (so "/" becomes "" and "/llm/" becomes "/llm") - Add send_redirect() method for HTTP redirects - Redirect requests to prefix without trailing slash (e.g., /llm -> /llm/) - Reject prefix collisions (e.g., /llmfoo when prefix is /llm) - Update man page example to use /llm instead of /lamafiler
1 parent 114457c commit 8f50fe6

5 files changed

Lines changed: 42 additions & 13 deletions

File tree

llamafile/flags.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,15 +313,17 @@ void llamafile_get_flags(int argc, char **argv) {
313313
if (!strcmp(flag, "--url-prefix")) {
314314
if (i == argc)
315315
missing("--url-prefix");
316-
FLAG_url_prefix = argv[i++];
316+
// Normalize: strip trailing slashes in-place (so "/" becomes "" and "/llm/" becomes "/llm")
317+
char *val = argv[i++];
318+
size_t len = strlen(val);
319+
while (len > 0 && val[len - 1] == '/') {
320+
val[--len] = '\0';
321+
}
322+
FLAG_url_prefix = val;
317323
if (!IsAcceptablePath(FLAG_url_prefix, -1)) {
318324
tinyprint(2, "error: --url-prefix must not have // or /. or /./ or /../\n", NULL);
319325
exit(1);
320326
}
321-
if (endswith(FLAG_url_prefix, "/")) {
322-
tinyprint(2, "error: --url-prefix must not be slash or end with slash\n", NULL);
323-
exit(1);
324-
}
325327
continue;
326328
}
327329

llamafile/server/client.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,21 @@ Client::send_error(int code, const char* reason)
323323
return false;
324324
}
325325

326+
// sends an http redirect response
327+
//
328+
// @param code must be a redirect status code (e.g. 301, 302, 307, 308)
329+
// @param location is the URL to redirect to
330+
bool
331+
Client::send_redirect(int code, const std::string_view& location)
332+
{
333+
SLOG("redirect %d %.*s", code, (int)location.size(), location.data());
334+
char* p = append_http_response_message(obuf_.p, code, nullptr);
335+
p = stpcpy(p, "Location: ");
336+
p = (char*)mempcpy(p, location.data(), location.size());
337+
p = stpcpy(p, "\r\n");
338+
return send_response(obuf_.p, p, "");
339+
}
340+
326341
// appends start of http response message to `p`
327342
//
328343
// after this function is called, more header lines may be appended.
@@ -677,11 +692,22 @@ Client::dispatcher()
677692
std::string_view p1 = path();
678693
WRITE64LE(method, msg_.method);
679694
SLOG("%s %.*s", method, (int)p1.size(), p1.data());
680-
if (!p1.starts_with(FLAG_url_prefix)) {
681-
SLOG("path prefix mismatch");
682-
return send_error(404);
695+
size_t prefix_len = strlen(FLAG_url_prefix);
696+
if (prefix_len > 0) {
697+
if (!p1.starts_with(FLAG_url_prefix)) {
698+
SLOG("path prefix mismatch");
699+
return send_error(404);
700+
}
701+
// Exact match (e.g. /llm) -> redirect to /llm/
702+
if (p1.size() == prefix_len)
703+
return send_redirect(301, std::string(FLAG_url_prefix) + "/");
704+
// Must have slash after prefix (e.g. /llm/foo not /llmfoo)
705+
if (p1[prefix_len] != '/') {
706+
SLOG("path prefix mismatch");
707+
return send_error(404);
708+
}
709+
p1 = p1.substr(prefix_len);
683710
}
684-
p1 = p1.substr(strlen(FLAG_url_prefix));
685711
if (!p1.starts_with("/") || !IsAcceptablePath(p1.data(), p1.size())) {
686712
SLOG("unacceptable path");
687713
return send_error(400);

llamafile/server/client.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct Client
8888
bool send_binary(const void*, size_t) __wur;
8989
void defer_cleanup(void (*)(void*), void*);
9090
bool send_error(int, const char* = nullptr);
91+
bool send_redirect(int, const std::string_view&);
9192
char* append_http_response_message(char*, int, const char* = nullptr);
9293
bool send_response(char*, char*, const std::string_view) __wur;
9394
bool send_response_start(char*, char*) __wur;

llamafile/server/main.1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Hide system prompt from web user interface.
9595
Hide llamafile logo icon from web ui.
9696
.It Fl Fl url-prefix Ar URLPREFIX
9797
Specifies a URL prefix (subdirectory) under which the HTTP server will
98-
make the API accessible, e.g. /lamafiler. Useful when running llamafiler
98+
make the API accessible, e.g. /llm. Useful when running llamafiler
9999
behind a reverse proxy such as NGINX or Redbean. By default, this is set
100100
to / (root).
101101
.It Fl Fl verbose

llamafile/server/main.1.asc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@
103103

104104
--url-prefix URLPREFIX
105105
Specifies a URL prefix (subdirectory) under which the HTTP
106-
server will make the API accessible, e.g. /lamafiler. Useful
107-
when running llamafiler behind a reverse proxy such as NGINX or
108-
Redbean. By default, this is set to / (root).
106+
server will make the API accessible, e.g. /llm. Useful when
107+
running llamafiler behind a reverse proxy such as NGINX or Red‐
108+
bean. By default, this is set to / (root).
109109

110110
--verbose
111111
Enable logging of diagnostic information. This flag is useful

0 commit comments

Comments
 (0)