forked from redis/redis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
http-redis.patch
105 lines (101 loc) · 4.5 KB
/
http-redis.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
diff --git a/src/networking.c b/src/networking.c
index 8d3e057b..76ff57ed 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -1273,6 +1273,33 @@ int writeToClient(client *c, int handler_installed) {
size_t objlen;
clientReplyBlock *o;
+ /* Only convert to HTTP for inline requests */
+ if (c->reqtype == PROTO_REQ_INLINE) {
+ char *http;
+ /* Determine status code. All errors in RESP start with '-' */
+ if (c->buf[0] == '-') {
+ http = "HTTP/1.1 400 Bad Request\r\nContent-Type: text/html\r\n\r\n";
+ } else {
+ http = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
+ }
+ /* Since we limited PROTO_INLINE_MAX_SIZE, we ensure there's enough space in the
+ * buffer for the HTTP prefix (and that c->reply is never used) */
+ size_t available = sizeof(c->buf)-c->bufpos;
+ size_t httpLen = strlen(http);
+ serverAssert(available >= httpLen);
+ /* See if we need to remove any RESP protocol lengths */
+ int bytesToRemove = 0;
+ if (c->buf[0] == '$' || c->buf[0] == '*') {
+ bytesToRemove = strchr(c->buf, '\n')-c->buf+1;
+ } else if (c->buf[0] == '=') {
+ bytesToRemove = strchr(c->buf, '\n')-c->buf+4; // Skip the 3-byte "content type"
+ }
+ /* Prepend the HTTP prefix */
+ memmove(c->buf+httpLen-bytesToRemove,c->buf,c->bufpos);
+ memcpy(c->buf,http,httpLen);
+ c->bufpos += httpLen-bytesToRemove;
+ }
+
while(clientHasPendingReplies(c)) {
if (c->bufpos > 0) {
nwritten = connWrite(c->conn,c->buf+c->sentlen,c->bufpos-c->sentlen);
@@ -1419,7 +1446,7 @@ void resetClient(client *c) {
redisCommandProc *prevcmd = c->cmd ? c->cmd->proc : NULL;
freeClientArgv(c);
- c->reqtype = 0;
+ // c->reqtype = 0; Needed in writeToClient
c->multibulklen = 0;
c->bulklen = -1;
@@ -1504,6 +1531,8 @@ int processInlineBuffer(client *c) {
/* Split the input buffer up to the \r\n */
querylen = newline-(c->querybuf+c->qb_pos);
aux = sdsnewlen(c->querybuf+c->qb_pos,querylen);
+ /* Strip " HTTP/1.1" (the last 9 characters) */
+ sdsrange(aux, 0, -10);
argv = sdssplitargs(aux,&argc);
sdsfree(aux);
if (argv == NULL) {
diff --git a/src/server.c b/src/server.c
index b7a6a928..933f779b 100644
--- a/src/server.c
+++ b/src/server.c
@@ -990,10 +990,6 @@ struct redisCommand redisCommandTable[] = {
"ok-loading ok-stale read-only",
0,NULL,0,0,0,0,0,0},
- {"host:",securityWarningCommand,-1,
- "ok-loading ok-stale read-only",
- 0,NULL,0,0,0,0,0,0},
-
{"latency",latencyCommand,-2,
"admin no-script ok-loading ok-stale",
0,NULL,0,0,0,0,0,0},
@@ -3428,8 +3424,8 @@ int processCommand(client *c) {
int i;
for (i=1; i < c->argc && sdslen(args) < 128; i++)
args = sdscatprintf(args, "`%.*s`, ", 128-(int)sdslen(args), (char*)c->argv[i]->ptr);
- addReplyErrorFormat(c,"unknown command `%s`, with args beginning with: %s",
- (char*)c->argv[0]->ptr, args);
+ /* We probably hit the HTTP headers, so just close the connection */
+ c->flags |= CLIENT_CLOSE_AFTER_REPLY;
sdsfree(args);
return C_OK;
} else if ((c->cmd->arity > 0 && c->cmd->arity != c->argc) ||
@@ -3459,7 +3455,8 @@ int processCommand(client *c) {
* ACLs. */
int acl_keypos;
int acl_retval = ACLCheckCommandPerm(c,&acl_keypos);
- if (acl_retval != ACL_OK) {
+ /* Always allow read access so unauth'ed users can see the homepage */
+ if (acl_retval != ACL_OK && !(c->cmd->flags & CMD_READONLY)) {
addACLLogEntry(c,acl_retval,acl_keypos,NULL);
flagTransaction(c);
if (acl_retval == ACL_DENIED_CMD)
diff --git a/src/server.h b/src/server.h
index a0858529..b8200e80 100644
--- a/src/server.h
+++ b/src/server.h
@@ -137,7 +137,7 @@ typedef long long ustime_t; /* microsecond time type. */
#define PROTO_MAX_QUERYBUF_LEN (1024*1024*1024) /* 1GB max query buffer. */
#define PROTO_IOBUF_LEN (1024*16) /* Generic I/O buffer size */
#define PROTO_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer */
-#define PROTO_INLINE_MAX_SIZE (1024*64) /* Max size of inline reads */
+#define PROTO_INLINE_MAX_SIZE (1024*16-256) /* Max size of inline reads (reduced to simplify output buffer handling) */
#define PROTO_MBULK_BIG_ARG (1024*32)
#define LONG_STR_SIZE 21 /* Bytes needed for long -> str + '\0' */
#define REDIS_AUTOSYNC_BYTES (1024*1024*32) /* fdatasync every 32MB */