Git Product home page Git Product logo

webdis's Introduction

Build

About Webdis

A very simple web server providing an HTTP interface to Redis. It uses hiredis, jansson, libevent, and http-parser.

Webdis depends on libevent-dev. You can install it on Ubuntu by typing sudo apt-get install libevent-dev or on macOS by typing brew install libevent.

To build Webdis with support for encrypted connections to Redis, see Building Webdis with SSL support.

Build and run from source

$ make clean all

$ ./webdis &

$ curl http://127.0.0.1:7379/SET/hello/world
→ {"SET":[true,"OK"]}

$ curl http://127.0.0.1:7379/GET/hello
→ {"GET":"world"}

$ curl -d "GET/hello" http://127.0.0.1:7379/
→ {"GET":"world"}

Configuration

Webdis is configured by a configuration file in JSON format, provided to the server as a command-line parameter:

./webdis /path/to/webdis.json

At start-up, Webdis will look for a file named webdis.json in the current directory if no file is specified on the command line.

This repository comes with a sample configuration file named webdis.json, to be used for local evaluation. Another file, webdis.prod.json, is provided as a starting point to build a production configuration file. Do not use either of these files in production without reviewing them.

The various features of Webdis are documented in this README.

Try in Docker

$ docker run --name webdis-test --rm -d -p 127.0.0.1:7379:7379 nicolas/webdis
0d2ce311a4834d403cc3e7cfd571b168ba40cede6a0e155a21507bb0bf7bee81

$ curl http://127.0.0.1:7379/PING
{"PING":[true,"PONG"]}

# To stop it:
$ docker stop webdis-test
0d2ce311a483

Docker repositories and Docker Content Trust

Webdis images are published on Docker Hub and Amazon ECR.

Docker Hub

$ docker pull nicolas/webdis:0.1.22
$ docker pull nicolas/webdis:latest

Starting from release 0.1.12 and including latest, Docker Hub images are signed (download public key). You should see the following key ID if you verify the trust:

$ docker trust inspect nicolas/webdis:0.1.22 --pretty

Signatures for nicolas/webdis:0.1.22

SIGNED TAG   DIGEST                                                             SIGNERS
0.1.22       5a7d342e3a9e5667fe05f045beae4b5042681d1d737f60843b7dfd11f96ab72f   (Repo Admin)

List of signers and their keys for nicolas/webdis:0.1.22

SIGNER      KEYS
nicolasff   dd0768b9d35d

Administrative keys for nicolas/webdis:0.1.22

  Repository Key:	fed0b56b8a8fd4d156fb2f47c2e8bd3eb61948b72a787c18e2fa3ea3233bba1a
  Root Key:	40be21f47831d593892370a8e3fc5bfffb16887c707bd81a6aed2088dc8f4bef

The signing keys are listed on this documentation page; please make sure they match what you see. The same documentation page details how to verify the signatures of multi-architecture images, and the tree of manifests used to build them.

Amazon Elastic Container Registry (ECR)

$ docker pull public.ecr.aws/nicolas/webdis:0.1.22
$ docker pull public.ecr.aws/nicolas/webdis:latest

A note on ECR and trust: AWS does not support Notary v2 at the time of this writing, although a security talk from 2020 mentions that the feature could be available in 2021.

The consequence is that Webdis images on ECR are not signed at this time.

They can still be verified, since the images uploaded there use the exact same hash as the ones on Docker Hub, which are signed. This means that you can verify the signature using the docker trust inspect command described above, as long as you also make sure that the image hash associated with the image on ECR matches the one shown on Docker Hub.

For more details about Content Trust validation with ECR images, refer to the article titled Webdis and Docker Content Trust in the Webdis documentation.

Multi-architecture images

Starting with release 0.1.19, Docker images for Webdis are published as manifest lists supporting multiple architectures. Each release points to an x86-64 image and an ARM64v8 image:

$ docker manifest inspect nicolas/webdis:0.1.19 | jq -r '.manifests | .[] | .platform.architecture + " -> " + .digest'
amd64 -> sha256:2ced2d99146e1bcaf10541d17dbac573cffd02237c3b268875be1868138d3b54
arm64 -> sha256:d026c5675552947b6a755439dfd58360e44a8860436f4eddfe9b26d050801248

By default docker pull will download only the relevant image for your architecture, but you can specify the platform to download the image for a specific architecture, e.g.

$ docker pull nicolas/webdis:0.1.19 --platform linux/arm64/v8

Build and run a Docker image locally

Clone the repository and open a terminal in the webdis directory, then run:

$ docker build -t webdis:custom .
[...]

$ docker run --name webdis-test --rm -d -p 127.0.0.1:7379:7379 webdis:custom
f0a2763fd456ac1f7ebff80eeafd6a5cd0fc7f06c69d0f7717fb2bdcec65926e

$ curl http://127.0.0.1:7379/PING
{"PING":[true,"PONG"]}

To stop it:

$ docker stop webdis-test
f0a2763fd456

Docker images and embedded Redis

ℹ️ The Docker images provided on Docker Hub under nicolas/webdis contain both Webdis and an embedded Redis server. They were built this way to make it easy to try Webdis without having to configure a Docker deployment with two containers, but this is likely not the best way to run Webdis in production.

The following documentation pages cover various such use cases:

More articles are available in the Webdis documentation.

Building Webdis with SSL support

Webdis needs libraries that provide TLS support to encrypt its connections to Redis:

  • On Alpine Linux, install openssl-dev with apk-add openssl-dev.
  • On Ubuntu, install libssl-dev with apt-get install libssl-dev.
  • On macOS with HomeBrew, install OpenSSL with brew install [email protected].

Then, build Webdis with SSL support enabled:

$ make SSL=1

Configuring Webdis with SSL

Once Redis is configured with SSL support (see this guide for step-by-step instructions), you can configure Webdis to connect to Redis over encrypted connections.

Add a block to webdis.json under a key named "ssl" placed at the root level, containing the following object:

{
    "enabled": true,
    "ca_cert_bundle": "/path/to/ca.crt",
    "path_to_certs": "/path/to/trusted/certs",
    "client_cert": "/path/to/redis.crt",
    "client_key": "/path/to/redis.key",
    "redis_sni": "redis.mydomain.tld"
}

This means that "ssl" should be at the same level as "redis_host", "redis_port", etc.

Important: the presence of the "ssl" configuration block alone does not necessarily enable secure connections to Redis. The key "enabled" inside this block must also be set to true, otherwise Webdis will keep using unencrypted connections.

Use the following table to match the Redis configuration keys to the fields under "ssl" in webdis.json:

Redis field Webdis field Purpose
tls-cert-file client_cert Client certificate
tls-key-file client_key Client key
tls-ca-cert-file ca_cert_bundle CA certificate bundle

Two other keys have no equivalent in redis.conf:

  • path_to_certs is an optional directory path where trusted CA certificate files are stored in an OpenSSL-compatible format.
  • redis_sni is an optional Redis server name, used as a server name indication (SNI) TLS extension.

See also the Hiredis docs and Hiredis source code for more information.

Running Redis and Webdis with SSL in Docker Compose

For a full tutorial showing how to configure and run Redis and Webdis under Docker Compose with SSL connections between the two services, head to the docs folder and open Running Webdis & Redis in Docker Compose with SSL connections.

SSL troubleshooting

Follow this table to diagnose issues with SSL connections to Redis.

Error message or issue Cause Solution
Unexpected key or incorrect value in webdis.json: 'ssl' Webdis is not compiled with SSL support Build webdis with make SSL=1
Unexpected key or incorrect value under 'ssl' Invalid configuration One or more keys in the ssl object in was not recognized, make sure they are all valid
Failed to load client certificate Invalid client certificate Verify the file that client_cert points to
Failed to load private key Invalid client key Verify the file that client_key points to
Failed to load CA Certificate or CA Path Invalid CA certificate bundle Verify the file that ca_cert_bundle points to
All requests fail with HTTP 503, logs show "Error disconnecting: Connection reset by peer" SSL disabled in config but Webdis connected to an SSL port Make sure enabled is set to true and that Webdis connects to the SSL port for Redis
Logs show "Server closed the connection" at start-up SSL connection failed The client key and/or client certificate was missing. Make sure the configuration is valid.
No error but all requests hang Webdis connected to the non-SSL port Make sure Webdis is connecting to the port set under tls-port in redis.conf

Features

  • GET and POST are supported, as well as PUT for file uploads (see example of PUT usage here).
  • JSON output by default, optional JSONP parameter (?jsonp=myFunction or ?callback=myFunction).
  • Raw Redis 2.0 protocol output with .raw suffix.
  • MessagePack output with .msg suffix.
  • HTTP 1.1 pipelining (70,000 http requests per second on a desktop Linux machine.)
  • Multi-threaded server, configurable number of worker threads.
  • WebSocket support (Currently using the specification from RFC 6455).
  • Connects to Redis using a TCP or UNIX socket.
  • Support for secure connections to Redis (requires Redis 6 or newer).
  • Support for "Keep-Alive" connections to Redis: add "hiredis": { "keep_alive_sec": 15 } to webdis.json to enable it with the default value. See the Hiredis documentation for details, the value configured in webdis.json is the interval passed to redisEnableKeepAliveWithInterval. Important: note how it is used to set the value for TCP_KEEPALIVE (the same value) and to compute the value for TCP_KEEPINTVL (integer, set to 1/3 × interval).
  • Restricted commands by IP range (CIDR subnet + mask) or HTTP Basic Auth, returning 403 errors.
  • Support for Redis authentication in the config file: set redis_auth to a single string to use a password value, or to an array of two strings to use username+password auth (new in Redis 6.0).
  • Environment variables can be used as values in the config file, starting with $ and in all caps (e.g. $REDIS_HOST).
  • Pub/Sub using Transfer-Encoding: chunked, works with JSONP as well. Webdis can be used as a Comet server.
  • Drop privileges on startup.
  • Custom Content-Type using a pre-defined file extension, or with ?type=some/thing.
  • URL-encoded parameters for binary data or slashes and question marks. For instance, %2f is decoded as / but not used as a command separator.
  • Logs, with a configurable verbosity.
  • Configurable fsync frequency for the log file:
    • Set "log_fsync": "auto" (default) to let the file system handle file persistence on its own.
    • Set "log_fsync": N where N is a number to call fsync every N milliseconds.
    • Set "log_fsync": "all" (very slow) to persist the log file to its storage device on each log message.
  • Cross-origin requests, usable with XMLHttpRequest2 (Cross-Origin Resource Sharing - CORS).
  • File upload with PUT.
  • With the JSON output, the return value of INFO is parsed and transformed into an object.
  • Optionally run as a daemon process: set "daemonize": true and "pidfile": "/var/run/webdis.pid" in webdis.json.
  • Default root object: Add "default_root": "/GET/index.html" in webdis.json to substitute the request to / with a Redis request.
  • HTTP request limit with http_max_request_size (in bytes, set to 128 MB by default).
  • Database selection in the URL, using e.g. /7/GET/key to run the command on DB 7.

Ideas, TODO…

  • Add better support for PUT, DELETE, HEAD, OPTIONS? How? For which commands?
    • This could be done using a “strict mode” with a table of commands and the verbs that can/must be used with each command. Strict mode would be optional, configurable. How would webdis know of new commands remains to be determined.
  • MULTI/EXEC/DISCARD/WATCH are disabled at the moment; find a way to use them.
  • Support POST of raw Redis protocol data, and execute the whole thing. This could be useful for MULTI/EXEC transactions.
  • Enrich config file:
    • Provide timeout (maybe for some commands only?). What should the response be? 504 Gateway Timeout? 503 Service Unavailable?
  • Multi-server support, using consistent hashing.
  • SSL/TLS?
    • It makes more sense to terminate SSL with nginx used as a reverse-proxy.
  • SPDY?
    • SPDY is mostly useful for parallel fetches. Not sure if it would make sense for Webdis.
  • Send your ideas using the github tracker, on twitter @yowgi or by e-mail to [email protected].

HTTP error codes

  • Unknown HTTP verb: 405 Method Not Allowed.
  • Redis is unreachable: 503 Service Unavailable.
  • Matching ETag sent using If-None-Match: 304 Not Modified.
  • Could also be used:
    • Timeout on the redis side: 503 Service Unavailable.
    • Missing key: 404 Not Found.
    • Unauthorized command (disabled in config file): 403 Forbidden.

Command format

The URI /COMMAND/arg0/arg1/.../argN.ext executes the command on Redis and returns the response to the client. GET, POST, and PUT are supported:

  • GET /COMMAND/arg0/.../argN.ext
  • POST / with COMMAND/arg0/.../argN in the HTTP body.
  • PUT /COMMAND/arg0.../argN-1 with argN in the HTTP body (see section on file uploads.)

.ext is an optional extension; it is not read as part of the last argument but only represents the output format. Several formats are available (see below).

Special characters: / and . have special meanings, / separates arguments and . changes the Content-Type. They can be replaced by %2f and %2e, respectively.

Redis authentication

Webdis can connect to a Redis server that requires credentials. For Redis versions before 6.0, provide the password as a single string in webdis.json using the key "redis_auth". For example:

    "redis_auth": "enter-password-here"

Redis 6.0 introduces a more granular access control system and switches from a single password to a pair of username and password. To use these two values with Webdis, set "redis_auth" to an array containing the two strings, e.g.

    "redis_auth": ["my-username", "my-password"]

This new authentication system is only supported in Webdis 0.1.13 and above.

ACL

Access control is configured in webdis.json. Each configuration tries to match a client profile according to two criteria:

Each ACL contains two lists of commands, enabled and disabled. All commands being enabled by default, it is up to the administrator to disable or re-enable them on a per-profile basis.

Examples:

{
    "disabled": ["DEBUG", "FLUSHDB", "FLUSHALL"],
},

{
    "http_basic_auth": "user:password",
    "disabled":        ["DEBUG", "FLUSHDB", "FLUSHALL"],
    "enabled":         ["SET"]
},

{
    "ip":      "192.168.10.0/24",
    "enabled": ["SET"]
},

{
    "http_basic_auth": "user:password",
    "ip":              "192.168.10.0/24",
    "enabled":         ["SET", "DEL"]
}

ACLs are interpreted in order, later authorizations superseding earlier ones if a client matches several. The special value "*" matches all commands.

ACLs and Websocket clients

These rules apply to WebSocket connections as well, although without support for HTTP Basic Auth filtering. IP filtering is supported.

For JSON-based WebSocket clients, a rejected command will return this object (sent as a string in a binary frame):

{"message": "Forbidden", "error": true, "http_status": 403}

The http_status code is an indicator of how Webdis would have responded if the client had used HTTP instead of a WebSocket connection, since WebSocket messages do not inherently have a status code.

For raw Redis protocol WebSocket clients, a rejected command will produce this error (sent as a string in a binary frame):

-ERR Forbidden\r\n

Environment variables

Environment variables can be used in webdis.json to read values from the environment instead of using constant values. For this, the value must be a string starting with a dollar symbol and written in all caps. For example, to make the redis host and port configurable via environment variables, use the following:

{
    "redis_host": "$REDIS_HOST",
    "redis_port": "$REDIS_PORT",
}

JSON output

JSON is the default output format. Each command returns a JSON object with the command as a key and the result as a value.

Examples:

// string
$ curl http://127.0.0.1:7379/GET/y
{"GET":"41"}

// number
$ curl http://127.0.0.1:7379/INCR/y
{"INCR":42}

// list
$ curl http://127.0.0.1:7379/LRANGE/x/0/1
{"LRANGE":["abc","def"]}

// status
$ curl http://127.0.0.1:7379/TYPE/y
{"TYPE":[true,"string"]}

// error, which is basically a status
$ curl http://127.0.0.1:7379/MAKE-ME-COFFEE
{"MAKE-ME-COFFEE":[false,"ERR unknown command 'MAKE-ME-COFFEE'"]}

// JSONP callback:
$ curl  "http://127.0.0.1:7379/TYPE/y?jsonp=myCustomFunction"
myCustomFunction({"TYPE":[true,"string"]})

RAW output

This is the raw output of Redis; enable it with the .raw suffix.

// string
$ curl http://127.0.0.1:7379/GET/z.raw
$5
hello

// number
$ curl http://127.0.0.1:7379/INCR/a.raw
:2

// list
$ curl http://127.0.0.1:7379/LRANGE/x/0/-1.raw
*2
$3
abc
$3
def

// status
$ curl http://127.0.0.1:7379/TYPE/y.raw
+zset

// error, which is basically a status
$ curl http://127.0.0.1:7379/MAKE-ME-COFFEE.raw
-ERR unknown command 'MAKE-ME-COFFEE'

Custom content-type

Several content-types are available:

  • .json for application/json (this is the default Content-Type).
  • .msg for application/x-msgpack. See https://msgpack.org/ for the specs.
  • .txt for text/plain
  • .html for text/html
  • .xhtml for application/xhtml+xml
  • .xml for text/xml
  • .png for image/png
  • .jpg or .jpeg for image/jpeg
  • Any other with the ?type=anything/youwant query string.
  • Add a custom separator for list responses with ?sep=, query string.
$ curl -v "http://127.0.0.1:7379/GET/hello.html"
[...]
< HTTP/1.1 200 OK
< Content-Type: text/html
< Date: Mon, 03 Jan 2011 20:43:36 GMT
< Content-Length: 137
<
<!DOCTYPE html>
<html>
[...]
</html>

$ curl -v "http://127.0.0.1:7379/GET/hello.txt"
[...]
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Date: Mon, 03 Jan 2011 20:43:36 GMT
< Content-Length: 137
[...]

$ curl -v "http://127.0.0.1:7379/GET/big-file?type=application/pdf"
[...]
< HTTP/1.1 200 OK
< Content-Type: application/pdf
< Date: Mon, 03 Jan 2011 20:45:12 GMT
[...]

File upload

Webdis supports file upload using HTTP PUT. The command URI is slightly different, as the last argument is taken from the HTTP body. For example: instead of /SET/key/value, the URI becomes /SET/key and the value is the entirety of the body. This works for other commands such as LPUSH, etc.

Uploading a binary file to webdis:

$ file redis-logo.png
redis-logo.png: PNG image, 513 x 197, 8-bit/color RGBA, non-interlaced

$ wc -c redis-logo.png
16744 redis-logo.png

$ curl -v --upload-file redis-logo.png http://127.0.0.1:7379/SET/logo
[...]
> PUT /SET/logo HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
> Host: 127.0.0.1:7379
> Accept: */*
> Content-Length: 16744
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Content-Type: application/json
< ETag: "0db1124cf79ffeb80aff6d199d5822f8"
< Date: Sun, 09 Jan 2011 16:48:19 GMT
< Content-Length: 19
<
{"SET":[true,"OK"]}

$ curl -vs http://127.0.0.1:7379/GET/logo.png -o out.png
> GET /GET/logo.png HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
> Host: 127.0.0.1:7379
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: image/png
< ETag: "1991df597267d70bf9066a7d11969da0"
< Date: Sun, 09 Jan 2011 16:50:51 GMT
< Content-Length: 16744

$ md5sum redis-logo.png out.png
1991df597267d70bf9066a7d11969da0  redis-logo.png
1991df597267d70bf9066a7d11969da0  out.png

The file was uploaded and re-downloaded properly: it has the same hash and the content-type was set properly thanks to the .png extension.

WebSockets

Webdis supports WebSocket clients implementing RFC 6455.

Important: WebSocket support is currently disabled by default. To enable WebSocket support, set the key named "websockets" to value true in webdis.json, e.g.

{
    "daemonize": false,
    "websockets": true,
}

(start and end of file omitted).

WebSockets are supported with the following formats, selected by the connection URL:

  • JSON (on / or /.json)
  • Raw Redis wire protocol (on /.raw)

Example:

function testJSON() {
    var jsonSocket = new WebSocket("ws://127.0.0.1:7379/.json");
    jsonSocket.onmessage = function(messageEvent) {
        console.log("JSON received:", messageEvent.data);
    };
    jsonSocket.onopen = function() {
        console.log("JSON socket connected!");
        jsonSocket.send(JSON.stringify(["SET", "hello", "world"]));
        jsonSocket.send(JSON.stringify(["GET", "hello"]));
    };
}
testJSON();

This produces the following output:

JSON socket connected!
JSON received: {"SET":[true,"OK"]}
JSON received: {"GET":"world"}

WebSockets HTML demo

The Webdis repository contains a demo web page with JavaScript code that can be used to test WebSocket support.

In a terminal, check out Webdis, build it, and configure it with WebSocket support:

$ cd ~/src/webdis
$ make
$ vim webdis.json      # (edit the file to add "websockets": true)
$ grep websockets webdis.json
    "websockets": true,
$ ./webdis

Then go to the tests/ directory and open websocket.html with a web browser.

Pub/Sub with chunked transfer encoding

Webdis exposes Redis PUB/SUB channels to HTTP clients, forwarding messages in the channel as they are published by Redis. This is done using chunked transfer encoding.

Example using XMLHttpRequest:

var previous_response_length = 0
xhr = new XMLHttpRequest()
xhr.open("GET", "http://127.0.0.1:7379/SUBSCRIBE/hello", true);
xhr.onreadystatechange = checkData;
xhr.send(null);

function checkData() {
    if(xhr.readyState == 3)  {
        response = xhr.responseText;
        chunk = response.slice(previous_response_length);
        previous_response_length = response.length;
        console.log(chunk);
    }
};

Publish messages to redis to see output similar to the following:

{"SUBSCRIBE":["subscribe","hello",1]}
{"SUBSCRIBE":["message","hello","some message"]}
{"SUBSCRIBE":["message","hello","some other message"]} 

webdis's People

Contributors

amir avatar andrebraga avatar baonq-me avatar bmatheny avatar boothj5 avatar ccvca avatar chx avatar davidk avatar granolamatt avatar jamessan avatar jessie-murray avatar jmorse avatar jollyroger avatar littlefrog avatar lucap avatar majklik avatar marsam avatar mrb avatar nicolasff avatar nrk avatar stefanoschaliasos avatar wasade avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webdis's Issues

Websockets and subscribe - seems to close on open

(NB: Newbie here)

I isue a SUBSCRIBE and I get back a subscribe reply as expected and then the websocket closes straight away. I was expecting it to stay up similarly to issuing the same SUBSCRIBE through a webbrowser where it stays open and recieves data as PUBLISH commands are issued.

What am I missing?

var jsonSocket = new WebSocket("ws://127.0.0.1:7379/.json");
jsonSocket.onopen = function() {
console.log("JSON socket connected!");
jsonSocket.send(JSON.stringify(["SUBSCRIBE", "test"]));
};
jsonSocket.onmessage = function(messageEvent) {
console.log("JSON received:", messageEvent.data);
};
jsonSocket.onclose = function() {
console.log("JSON closed");
};

Console output:

JSON socket connected! test.html:55
JSON received: {"SUBSCRIBE":["subscribe","test",1]} test.html:60
JSON closed

[BUG] Webdis exits immediately on start on linux x86_64

Hello!

I'm trying to use webdis on linux x86_64 with the latest git master HEAD (28ec185) and tries to start the ./webdis executable with the default webdis.json file in the repos.

But ./webdis immediately exits at startup, and nothing is listening on the port 7379. turning off the daemonize option in webdis.json gives the same result.

the last few lines of the strace output look like this:

mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f342ce70000
mprotect(0x7f342ce70000, 4096, PROT_NONE) = 0
clone(child_stack=0x7f342d66fff0,     flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f342d6709e0, tls=0x7f342d670710, child_tidptr=0x7f342d6709e0) = 3999
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 23
setsockopt(23, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
fcntl(23, F_SETFD, 0x800 /* FD_??? */)  = 0
bind(23, {sa_family=AF_INET, sin_port=htons(7379), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(23, 128)                         = 0
exit_group(0)                           = ?

The output of uname -a:

Linux agentzh-thinkpad 2.6.33.1 #2 SMP Fri Mar 26 02:09:08 CDT 2010 x86_64 Intel(R) Core(TM)2 Duo CPU T9600 @ 2.80GHz GenuineIntel GNU/Linux

The output of cc -v

$ cc -v
Reading specs from /usr/lib64/gcc/x86_64-slackware-linux/4.4.3/specs
Target: x86_64-slackware-linux
Configured with: ../gcc-4.4.3/configure --prefix=/usr --libdir=/usr/lib64 --enable-shared --enable-bootstrap --enable-languages=ada,c,c++,fortran,java,objc --enable-threads=posix --enable-checking=release --with-system-zlib --with-python-dir=/lib64/python2.6/site-packages --disable-libunwind-exceptions --enable-__cxa_atexit --enable-libssp --with-gnu-ld --verbose --disable-multilib --target=x86_64-slackware-linux --build=x86_64-slackware-linux --host=x86_64-slackware-linux
Thread model: posix
gcc version 4.4.3 (GCC) 

Any clues?

SUBSCRIBE closes connection, does not keep-alive?

I'm unable to subscribe to a channel through HTTP. It appears the connection gets closed as soon as the subscription is done, and that HTTP headers (ie. content-type) are completely missing from the response. Should it work?

$ tests/pubsub -r 10 -w 10 -n 10
# kept it running, can see in the Redis log the SUBSCRIBE commands and the PUBLISH commands
Received 0 messages from 10 writers to 10 readers through 1 channels in 273.75 sec: received 0.00 msg/sec
$ telnet localhost 7379
GET /SUBSCRIBE/chan HTTP/1.1

24
{"SUBSCRIBE":["subscribe","chan",1]}
Connection closed by foreign host.

start as daemon

Your work is great!
Please, tell me how i can start on Debian as daemon for production mode

Pidfile creation and signal handling

Hello, Nicolas!

It would be great if webdis could receive signals and write its pidfile somewhere.

Pidfiles are great tools which help to maintain running process and identify the correct process among several servers with the same name.

Signal handling is one of the commonly used features for such things like log rotating. For example, when SIGHUP is received, the deamon commonly should reread it's config file (e.g. reload) and reopen log files. This is common technique used by logrotate.

Format of redis_auth in webdis.json

What is the format of data in redis_auth? I am using a redis server with authentication enabled. Is the value a string consisting of "username:password" or is it something else? Thanks!

linux build script

Hi,

Is there a build instruction?

I got this error:

bran@r610:/downloads/webdis$ make
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -o webdis.o webdis.c
webdis.c:4: fatal error: evhttp.h: No such file or directory
compilation terminated.
make: *** [webdis.o] Error 1
bran@r610:
/downloads/webdis$

SUBSCRIBE / PUBLISH fails

Hi,

We are using webdis only with the publish / subscribe commands. We have about 5000 to 50000 connections per day, each lasting about 30 seconds, and after some period (depending on load) webdis subscribe stops working. Our webdis and redis instances are on the same server.

Looking at the redis logs, it seems redis is refusing connections to webdis, but webdis does not report any problem. If we restart webdis everything works fine again.

Any ideas to find out what the issue is here? Are too many connections be kept open by webdis?

Thanks,
Tim

Google Chrome 19/20 websocket

Running the last webdis version, I get this error message from a Google Chrome 20 client :
Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch
and no error from a Google Chrome 19 client.
Is there any change in websocket from Chrome 19/20 ?

Google Chrome Version 20.0.1132.47 on Ubuntu 10.04 64 bits
Google Chrome Version 20.0.1132.47 on Ubuntu 10.04 64 bits

webdis compile error

I've got a large error output:

cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o webdis.o webdis.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o cmd.o cmd.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o worker.o worker.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o slog.o slog.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o server.o server.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o libb64/cencode.o libb64/cencode.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o acl.o acl.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o md5/md5.o md5/md5.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o http.o http.c
http.c: In function ‘http_response_write’:
http.c:138:9: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o client.o client.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o websocket.o websocket.c
websocket.c: In function ‘ws_handshake_reply’:
websocket.c:76:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o pool.o pool.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o conf.o conf.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o formats/json.o formats/json.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o formats/raw.o formats/raw.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o formats/common.o formats/common.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o formats/custom-type.o formats/custom-type.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o formats/bson.o formats/bson.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o hiredis/hiredis.o hiredis/hiredis.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o hiredis/sds.o hiredis/sds.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o hiredis/net.o hiredis/net.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o hiredis/async.o hiredis/async.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o hiredis/dict.o hiredis/dict.c
hiredis/dict.c:53:21: warning: ‘dictGenHashFunction’ defined but not used [-Wunused-function]
hiredis/dict.c:73:14: warning: ‘dictCreate’ defined but not used [-Wunused-function]
hiredis/dict.c:160:12: warning: ‘dictReplace’ defined but not used [-Wunused-function]
hiredis/dict.c:182:12: warning: ‘dictDelete’ defined but not used [-Wunused-function]
hiredis/dict.c:238:13: warning: ‘dictRelease’ defined but not used [-Wunused-function]
hiredis/dict.c:258:22: warning: ‘dictGetIterator’ defined but not used [-Wunused-function]
hiredis/dict.c:268:19: warning: ‘dictNext’ defined but not used [-Wunused-function]
hiredis/dict.c:288:13: warning: ‘dictReleaseIterator’ defined but not used [-Wunused-function]
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o jansson/src/dump.o jansson/src/dump.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o jansson/src/error.o jansson/src/error.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o jansson/src/hashtable.o jansson/src/hashtable.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o jansson/src/load.o jansson/src/load.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o jansson/src/strbuffer.o jansson/src/strbuffer.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o jansson/src/utf.o jansson/src/utf.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o jansson/src/value.o jansson/src/value.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o jansson/src/variadic.o jansson/src/variadic.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o http-parser/http_parser.o http-parser/http_parser.c
cc -levent -pthread -o webdis webdis.o cmd.o worker.o slog.o server.o libb64/cencode.o acl.o md5/md5.o http.o client.o websocket.o pool.o conf.o formats/json.o formats/raw.o formats/common.o formats/custom-type.o formats/bson.o hiredis/hiredis.o hiredis/sds.o hiredis/net.o hiredis/async.o hiredis/dict.o jansson/src/dump.o jansson/src/error.o jansson/src/hashtable.o jansson/src/load.o jansson/src/strbuffer.o jansson/src/utf.o jansson/src/value.o jansson/src/variadic.o http-parser/http_parser.o
worker.o: In function worker_main': worker.c:(.text+0xd): undefined reference toevent_base_new'
worker.c:(.text+0x29): undefined reference to event_set' worker.c:(.text+0x35): undefined reference toevent_base_set'
worker.c:(.text+0x3f): undefined reference to event_add' worker.c:(.text+0x6b): undefined reference toevent_base_dispatch'
worker.o: In function worker_can_read': worker.c:(.text+0xd2): undefined reference toevent_set'
worker.c:(.text+0xe5): undefined reference to event_base_set' worker.o: In functionworker_on_new_client':
worker.c:(.text+0x1f5): undefined reference to event_set' worker.c:(.text+0x208): undefined reference toevent_base_set'
worker.c:(.text+0x212): undefined reference to event_add' worker.o: In functionworker_monitor_input':
worker.c:(.text+0x2b8): undefined reference to event_set' worker.c:(.text+0x2cb): undefined reference toevent_base_set'
worker.o: In function worker_can_read': worker.c:(.text+0xf5): undefined reference toevent_add'
worker.o: In function worker_monitor_input': worker.c:(.text+0x2e3): undefined reference toevent_add'
server.o: In function server_start': server.c:(.text+0x217): undefined reference toevent_reinit'
server.c:(.text+0x338): undefined reference to event_base_new' server.c:(.text+0x35a): undefined reference toevent_set'
server.c:(.text+0x369): undefined reference to event_base_set' server.c:(.text+0x373): undefined reference toevent_add'
server.c:(.text+0x37f): undefined reference to event_base_dispatch' http.o: In functionhttp_can_write':
http.c:(.text+0x63): undefined reference to event_set' http.c:(.text+0x76): undefined reference toevent_base_set'
http.o: In function http_schedule_write': http.c:(.text+0x3f1): undefined reference toevent_set'
http.c:(.text+0x404): undefined reference to event_base_set' http.o: In functionhttp_response_write':
http.c:(.text+0x6b1): undefined reference to event_set' http.c:(.text+0x6c4): undefined reference toevent_base_set'
http.c:(.text+0x6ce): undefined reference to event_add' http.o: In functionhttp_response_write_chunk':
http.c:(.text+0xc36): undefined reference to event_set' http.c:(.text+0xc49): undefined reference toevent_base_set'
http.c:(.text+0xc53): undefined reference to event_add' http.o: In functionhttp_can_write':
http.c:(.text+0x84): undefined reference to event_add' http.o: In functionhttp_schedule_write':
http.c:(.text+0x40f): undefined reference to event_add' pool.o: In functionredisLibeventCleanup':
pool.c:(.text+0x89): undefined reference to event_del' pool.c:(.text+0x95): undefined reference toevent_del'
pool.o: In function pool_on_disconnect': pool.c:(.text+0x179): undefined reference toevent_set'
pool.c:(.text+0x189): undefined reference to event_base_set' pool.o: In functionredisLibeventAttach':
pool.c:(.text+0x266): undefined reference to event_set' pool.c:(.text+0x281): undefined reference toevent_set'
pool.c:(.text+0x28c): undefined reference to event_base_set' pool.c:(.text+0x297): undefined reference toevent_base_set'
pool.o: In function pool_can_connect': pool.c:(.text+0x3dd): undefined reference toevent_set'
pool.c:(.text+0x3ed): undefined reference to event_base_set' pool.o: In functionpool_connect':
pool.c:(.text+0x595): undefined reference to event_set' pool.c:(.text+0x5a5): undefined reference toevent_base_set'
pool.c:(.text+0x5b6): undefined reference to event_add' pool.o: In functionredisLibeventAddWrite':
pool.c:(.text+0x6a): undefined reference to event_add' pool.o: In functionredisLibeventAddRead':
pool.c:(.text+0x77): undefined reference to event_add' pool.o: In functionredisLibeventDelWrite':
pool.c:(.text+0xb8): undefined reference to event_del' pool.o: In functionredisLibeventDelRead':
pool.c:(.text+0xc5): undefined reference to event_del' pool.o: In functionpool_on_disconnect':
pool.c:(.text+0x19e): undefined reference to event_add' pool.o: In functionpool_can_connect':
pool.c:(.text+0x402): undefined reference to `event_add'
collect2: ld returned 1 exit status

make: *** [webdis] Помилка 1

Seams like linker cannot find reference to libevent but I'm sure it's installed on my Ubuntu x86_64 (via Synaptic) - the library and dev-header. So I'm confused what else might it be. I think some errors may be caused because I've got not proper version of libevent installed. I use

  • libevent-2.0.12.
  • libevent-dev-2.0.12

I've got also

  • libevent-1.4
    installed on my system. Would be appreciate for the fast reply.
    Thank you.

Have deamonize?

Good project. I try to use at my work, but in test webdis has no deamonize option, and if i use nohup, i have problems and not correctly work.

Only access first db on a server?

After looking at the source I see no means to configure webdis to connect to a specific database on the redis server. Seem a significant omission to me. That may be because it makes it useless for me. ;)

Output from command HGETALL

Now this command output raw array, where keys and hash value are in one big array.

E.g.:

HGETALL: [
"testhashkey",
"valueofhashkey",
"testhashkey2",
"value2",
....
]

Maybe is not good to processing. In good examples - HGETALL is object (assoc array), where hashkeys are key and his value are values of this key, e.g.

HGETALL:{
"testkey":"testvalue",
"testkey2": "value2"
}

manage multiple Redis instances

Is it possible to add the possibility to manage multiples Redis instances ?
The URL scheme could be "/instance_name/commande/param".
Each instance should have it's own configuration section with it's own ACL.

Why ?

  • it's better to have multiples small Redis instance instead of one big for reducing memory usage while writing snapshot to disk or just because you have differents persitance needs in a big dataset.
  • it's better to have only one Webdis instance when used as the primary frontend binded on port 80.
  • it's possible to use multiples Redis instance for managing sort of namespaces with differents ACL (readonly keys for example).

Dies when sending a message to a client listening through a websocket

Test page:

<script type="text/javascript"> 
function testJSON() {
    var jsonSocket = new WebSocket("ws://localhost:7379/.json");
    jsonSocket.onopen = function() {

        console.log("JSON socket connected!");
        jsonSocket.send(JSON.stringify(["SUBSCRIBE", "chan"]));
    };
    jsonSocket.onmessage = function(messageEvent) {
        console.log("JSON received:", messageEvent.data);
    };
}
testJSON();
</script>
  1. Loaded test page on Google Chrome
  2. WIth another connection to Redis sent the message: PUBLISH chan Moo4

Webdis shuts down, this is what gets printed:

{"":["message","chan","Moo4"]}?*** glibc detected *** ./webdis: double free or corruption (fasttop): 0x00007f8e440011a0 *** ======= Backtrace: ========= /lib64/libc.so.6(+0x75386)[0x7f8e4eb6b386] ./webdis[0x408b5d] ./webdis[0x407bb1] ./webdis[0x4103b2] /usr/lib64/libevent-1.4.so.2(event_base_loop+0x3e4)[0x7f8e4f08bb44] ./webdis[0x402f1f] /lib64/libpthread.so.0(+0x77e1)[0x7f8e4ee6f7e1] /lib64/libc.so.6(clone+0x6d)[0x7f8e4ebd727d] ======= Memory map: ======== 00400000-0041f000 r-xp 00000000 ca:01 151681 /tmp/webdis/webdis 0061f000-00620000 rw-p 0001f000 ca:01 151681 /tmp/webdis/webdis 0093b000-0095c000 rw-p 00000000 00:00 0 [heap] 7f8e38000000-7f8e38021000 rw-p 00000000 00:00 0 7f8e38021000-7f8e3c000000 ---p 00000000 00:00 0 7f8e40000000-7f8e40021000 rw-p 00000000 00:00 0 7f8e40021000-7f8e44000000 ---p 00000000 00:00 0 7f8e44000000-7f8e44021000 rw-p 00000000 00:00 0 7f8e44021000-7f8e48000000 ---p 00000000 00:00 0 7f8e48000000-7f8e48021000 rw-p 00000000 00:00 0 7f8e48021000-7f8e4c000000 ---p 00000000 00:00 0 7f8e4c2a1000-7f8e4c2b7000 r-xp 00000000 ca:01 428 /lib64/libgcc_s-4.4.4-20100726.so.1 7f8e4c2b7000-7f8e4c4b6000 ---p 00016000 ca:01 428 /lib64/libgcc_s-4.4.4-20100726.so.1 7f8e4c4b6000-7f8e4c4b7000 rw-p 00015000 ca:01 428 /lib64/libgcc_s-4.4.4-20100726.so.1 7f8e4c4b7000-7f8e4c4b8000 ---p 00000000 00:00 0 7f8e4c4b8000-7f8e4ccb8000 rw-p 00000000 00:00 0 7f8e4ccb8000-7f8e4ccb9000 ---p 00000000 00:00 0 7f8e4ccb9000-7f8e4d4b9000 rw-p 00000000 00:00 0 7f8e4d4b9000-7f8e4d4ba000 ---p 00000000 00:00 0 7f8e4d4ba000-7f8e4dcba000 rw-p 00000000 00:00 0 7f8e4dcba000-7f8e4dcbb000 ---p 00000000 00:00 0 7f8e4dcbb000-7f8e4e4bb000 rw-p 00000000 00:00 0 7f8e4e4bb000-7f8e4e4d1000 r-xp 00000000 ca:01 8115 /lib64/libresolv-2.12.so 7f8e4e4d1000-7f8e4e6d1000 ---p 00016000 ca:01 8115 /lib64/libresolv-2.12.so 7f8e4e6d1000-7f8e4e6d2000 r--p 00016000 ca:01 8115 /lib64/libresolv-2.12.so 7f8e4e6d2000-7f8e4e6d3000 rw-p 00017000 ca:01 8115 /lib64/libresolv-2.12.so 7f8e4e6d3000-7f8e4e6d5000 rw-p 00000000 00:00 0 7f8e4e6d5000-7f8e4e6dc000 r-xp 00000000 ca:01 8117 /lib64/librt-2.12.so 7f8e4e6dc000-7f8e4e8db000 ---p 00007000 ca:01 8117 /lib64/librt-2.12.so 7f8e4e8db000-7f8e4e8dc000 r--p 00006000 ca:01 8117 /lib64/librt-2.12.so 7f8e4e8dc000-7f8e4e8dd000 rw-p 00007000 ca:01 8117 /lib64/librt-2.12.so 7f8e4e8dd000-7f8e4e8f3000 r-xp 00000000 ca:01 8099 /lib64/libnsl-2.12.so 7f8e4e8f3000-7f8e4eaf2000 ---p 00016000 ca:01 8099 /lib64/libnsl-2.12.so 7f8e4eaf2000-7f8e4eaf3000 r--p 00015000 ca:01 8099 /lib64/libnsl-2.12.so 7f8e4eaf3000-7f8e4eaf4000 rw-p 00016000 ca:01 8099 /lib64/libnsl-2.12.so 7f8e4eaf4000-7f8e4eaf6000 rw-p 00000000 00:00 0 7f8e4eaf6000-7f8e4ec5f000 r-xp 00000000 ca:01 8089 /lib64/libc-2.12.so 7f8e4ec5f000-7f8e4ee5e000 ---p 00169000 ca:01 8089 /lib64/libc-2.12.so 7f8e4ee5e000-7f8e4ee62000 r--p 00168000 ca:01 8089 /lib64/libc-2.12.so 7f8e4ee62000-7f8e4ee63000 rw-p 0016c000 ca:01 8089 /lib64/libc-2.12.so 7f8e4ee63000-7f8e4ee68000 rw-p 00000000 00:00 0 7f8e4ee68000-7f8e4ee7f000 r-xp 00000000 ca:01 8113 /lib64/libpthread-2.12.so 7f8e4ee7f000-7f8e4f07f000 ---p 00017000 ca:01 8113 /lib64/libpthread-2.12.so 7f8e4f07f000-7f8e4f080000 r--p 00017000 ca:01 8113 /lib64/libpthread-2.12.so 7f8e4f080000-7f8e4f081000 rw-p 00018000 ca:01 8113 /lib64/libpthread-2.12.so 7f8e4f081000-7f8e4f085000 rw-p 00000000 00:00 0 7f8e4f085000-7f8e4f09e000 r-xp 00000000 ca:01 9887 /usr/lib64/libevent-1.4.so.2.1.3 7f8e4f09e000-7f8e4f29e000 ---p 00019000 ca:01 9887 /usr/lib64/libevent-1.4.so.2.1.3 7f8e4f29e000-7f8e4f29f000 rw-p 00019000 ca:01 9887 /usr/lib64/libevent-1.4.so.2.1.3 7f8e4f29f000-7f8e4f2a0000 rw-p 00000000 00:00 0 7f8e4f2a0000-7f8e4f2be000 r-xp 00000000 ca:01 8081 /lib64/ld-2.12.so 7f8e4f4b0000-7f8e4f4b5000 rw-p 00000000 00:00 0 7f8e4f4bd000-7f8e4f4be000 rw-p 00000000 00:00 0 7f8e4f4be000-7f8e4f4bf000 r--p 0001e000 ca:01 8081 /lib64/ld-2.12.so 7f8e4f4bf000-7f8e4f4c0000 rw-p 0001f000 ca:01 8081 /lib64/ld-2.12.so 7f8e4f4c0000-7f8e4f4c1000 rw-p 00000000 00:00 0 7fff239d1000-7fff239f2000 rw-p 00000000 00:00 0 [stack] 7fff239ff000-7fff23a00000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

serve a customizable page for index URL "/"

I would like to use webdis to serve HTML5 app based on redis. The webdis URL scheme "/command/arg0/arg1" is ok for my use except i would like to be able to customize the index URL "/" for serving my one file html app.

What do you think about this ?

MULTI/EXEC/

Just wondering when/what are the thoughts on adding MULTI/EXEC support.

Logging Not Working

{
"redis_host": "127.0.0.1",
"redis_port": 6379,
"redis_auth": null,
"http_host": "192.168.0.110",
"http_port": 7369,
"threads": 1,
"pool_size": 10,
"daemonize": true,
"websockets": false,
"database": 0,
"acl": [
{
"disabled": ["DEBUG"]
},
{
"http_basic_auth": "user:password",
"enabled": ["DEBUG"]
}
],
"verbosity": 0,
"logfile": "/var/log/webdis/webdis.log"
}

The directory permissions as set to 777 and the log file permissions are set to 777. I also tried different numbers in verbosity. And no luck. Any ideas what I am doing wrong?

I cloned the git repository and compiled the code on my server. It runs but just doesn't log. I am having some issues and logging would be a huge help.

webdis slow publish rps on slow subscribe clients

Hi, Nicolas

I made a test of publish rps with slow subscribe scenario and compared with redis-py client. I do it in python.

test1:

python test_webdis_subscribe.py

ab -n 4000 -c 1 http://127.0.0.1:7379/PUBLISH/ch:test/hi
Request per second: 4000 rps

ab -n 10000 -c 1 http://127.0.0.1:7379/PUBLISH/ch:test/hi
Request per second: 161.50 rps

test2:

python test_redispy_subscribe.py

python test_redispy_publish.py 10000
Request per second: 4090 rps

161rps isn't normal compared with 4000rps with webdis. It seems publish rps affected by slow subscribe clients.

partial code can be found at: https://gist.github.com/988375

ACL config disable ["*"] supress all enabled commands

I want to enable just "PUBLISH" command for one host. I suppose the following configuration will work, which is not.

"acl": [
{
"ip": "127.0.0.1",
"disabled": ["*"],
"enabled": ["PUBLISH"]
}
]

403 got when try to PUBLISH.

It should work like nginx deny all and allow one directive.

Compile error: event.h: No such file or directory

ruby-1.8.7-p334 user1@server webdis [master] $ make
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o webdis.o webdis.c
In file included from webdis.c:1:
server.h:4:19: error: event.h: No such file or directory
In file included from webdis.c:1:
server.h:14: error: field 'ev' has incomplete type
make: *** [webdis.o] Error 1
ruby-1.8.7-p334 user1@server webdis [master] $ git commit 04774aa

I guess I'll just go backwards to commit: 07daf02
as that is working on my dev machine :)

http_parser_settings' callback not called

I ported webdis code into a HTTP server that only serve as a server.

I have read most of webdis source code. I use cscope to find where http_parser_settings's callback calling, but following callbacks not been called:

  • on_url
  • on_query_string
  • on_message_complete
  • on_header_field
  • on_header_value

This confused me a lot. While a client object comes, I don't know whether it's request is complete, as I expect, while a client HTTP request complete, on_message_complete should be called.

Why set these callbacks that no code has really executed?

subscribe with ending / following a Ctrl+C crash webdis server

curl http://192.168.60.99:7379/SUBSCRIBE/hello/world/

then Ctrl+C terminate it, the server will crash.

*** glibc detected *** webdis: free(): invalid pointer: 0x0000003203552a38 ***

[root@jeb webdis]# ======= Backtrace: =========
/lib64/libc.so.6[0x320327230f]
/lib64/libc.so.6(cfree+0x4b)[0x320327276b]
webdis[0x401d3d]
webdis[0x407884]
webdis[0x40d1ff]
webdis[0x405415]
webdis[0x402931]
/usr/local/libevent-2.0.11/lib/libevent-2.0.so.5(event_base_loop+0x509)[0x2b9bb61bfdf9]
webdis[0x40283f]
/lib64/libpthread.so.0[0x3203a0673d]
/lib64/libc.so.6(clone+0x6d)[0x32032d3d1d]
======= Memory map: ========
00400000-0041c000 r-xp 00000000 fd:00 7406970 /usr/local/webdis-0.1.0/bin/webdis
0061b000-0061c000 rw-p 0001b000 fd:00 7406970 /usr/local/webdis-0.1.0/bin/webdis
02a12000-02a33000 rw-p 02a12000 00:00 0 [heap]
41d8f000-41d90000 ---p 41d8f000 00:00 0
41d90000-42790000 rw-p 41d90000 00:00 0
42790000-42791000 ---p 42790000 00:00 0
42791000-43191000 rw-p 42791000 00:00 0
43191000-43192000 ---p 43191000 00:00 0
43192000-43b92000 rw-p 43192000 00:00 0
43b92000-43b93000 ---p 43b92000 00:00 0
43b93000-44593000 rw-p 43b93000 00:00 0
3202e00000-3202e1c000 r-xp 00000000 fd:00 13271358 /lib64/ld-2.5.so
320301b000-320301c000 r--p 0001b000 fd:00 13271358 /lib64/ld-2.5.so
320301c000-320301d000 rw-p 0001c000 fd:00 13271358 /lib64/ld-2.5.so
3203200000-320334e000 r-xp 00000000 fd:00 13271359 /lib64/libc-2.5.so
320334e000-320354d000 ---p 0014e000 fd:00 13271359 /lib64/libc-2.5.so
320354d000-3203551000 r--p 0014d000 fd:00 13271359 /lib64/libc-2.5.so
3203551000-3203552000 rw-p 00151000 fd:00 13271359 /lib64/libc-2.5.so
3203552000-3203557000 rw-p 3203552000 00:00 0
3203a00000-3203a16000 r-xp 00000000 fd:00 13271364 /lib64/libpthread-2.5.so
3203a16000-3203c15000 ---p 00016000 fd:00 13271364 /lib64/libpthread-2.5.so
3203c15000-3203c16000 r--p 00015000 fd:00 13271364 /lib64/libpthread-2.5.so
3203c16000-3203c17000 rw-p 00016000 fd:00 13271364 /lib64/libpthread-2.5.so
3203c17000-3203c1b000 rw-p 3203c17000 00:00 0
3204200000-3204207000 r-xp 00000000 fd:00 13271366 /lib64/librt-2.5.so
3204207000-3204407000 ---p 00007000 fd:00 13271366 /lib64/librt-2.5.so
3204407000-3204408000 r--p 00007000 fd:00 13271366 /lib64/librt-2.5.so
3204408000-3204409000 rw-p 00008000 fd:00 13271366 /lib64/librt-2.5.so
3206200000-320620d000 r-xp 00000000 fd:00 13271093 /lib64/libgcc_s-4.1.2-20080825.so.1
320620d000-320640d000 ---p 0000d000 fd:00 13271093 /lib64/libgcc_s-4.1.2-20080825.so.1
320640d000-320640e000 rw-p 0000d000 fd:00 13271093 /lib64/libgcc_s-4.1.2-20080825.so.1
2aaaac000000-2aaaac021000 rw-p 2aaaac000000 00:00 0
2aaaac021000-2aaab0000000 ---p 2aaaac021000 00:00 0
2b9bb6199000-2b9bb619a000 rw-p 2b9bb6199000 00:00 0
2b9bb61ae000-2b9bb61af000 rw-p 2b9bb61ae000 00:00 0
2b9bb61af000-2b9bb61ef000 r-xp 00000000 fd:00 7342702 /usr/local/libevent-2.0.11/lib/libevent-2.0.so.5.1.0
2b9bb61ef000-2b9bb63ee000 ---p 00040000 fd:00 7342702 /usr/local/libevent-2.0.11/lib/libevent-2.0.so.5.1.0
2b9bb63ee000-2b9bb63f0000 rw-p 0003f000 fd:00 7342702 /usr/local/libevent-2.0.11/lib/libevent-2.0.so.5.1.0
2b9bb63f0000-2b9bb63f2000 rw-p 2b9bb63f0000 00:00 0
7fff58562000-7fff58577000 rw-p 7ffffffea000 00:00 0 [stack]
ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0 [vdso]

webdis crash when redis max connection exceeded

Hi, Nicolas

webdis will crash when redis max connection exceeded. You may reproduce it with the following steps:

  1. set the redis max connection: maxclient=256
  2. ab -n 100000 -c 1 http://127.0.0.1:7379/PUBLISH/ch:hello/world
  3. ab -n 255 -c 1 http://127.0.0.1:7379/SUBSCRIBE/ch:hello
  4. ab -n 2 -c 1 http://127.0.0.1:7379/SUBSCRIBE/ch:hello ( webdis will crash)

webdis will crash, strace of the webdis process as following:

clock_gettime(CLOCK_MONOTONIC, {10141, 66579365}) = 0
accept(12, {sa_family=AF_INET, sin_port=htons(43283), sin_addr=inet_addr("192.168.60.66")}, [16]) = 299
write(6, "\0\276\1\254\252*\0\0", 8)    = 8
epoll_wait(13, {{EPOLLIN, {u32=12, u64=12}}}, 32, 4294967295) = 1
clock_gettime(CLOCK_MONOTONIC, {10141, 68061365}) = 0
accept(12, {sa_family=AF_INET, sin_port=htons(43284), sin_addr=inet_addr("192.168.60.66")}, [16]) = 300
write(8, "\220\277\1\254\252*\0\0", 8)  = 8
epoll_wait(13, {{EPOLLIN, {u32=12, u64=12}}}, 32, 4294967295) = 1
clock_gettime(CLOCK_MONOTONIC, {10141, 69825365}) = 0
accept(12, {sa_family=AF_INET, sin_port=htons(43285), sin_addr=inet_addr("192.168.60.66")}, [16]) = 303
write(10, "\0\303\1\254\252*\0\0", 8)   = 8
epoll_wait(13,  <unfinished ...>
+++ killed by SIGSEGV +++

Error reply is expected rather than crash.

DB access restriction

I think, wery good will be add DB access restriction to config file. In simple use case, we using any database for private info storing, but one or two to public access from HTTP.

This maybe that (at config):

databases: 2

If option no set or null, default database is 0

INFO command responce

If we get INFO command response, we have JSON, but in the data we have all lines from Redis output, joined with \r\n. Mybe correctly output for this command generated full json structure with one key per each info params? With this we have direct use response in JS or other web application without decoding and preprocessing.

Unexpected Segmentation fault

Running webdis with ~100-150 connections.
HBGET, MGET, GET, SUBSCRIBE, SMEMBERS, RPUSH commands are used.

Time-to-time, approximately once a day we have webdis crash.
Here a gdb backtrace:

Program terminated with signal 11, Segmentation fault. (gdb) bt #0 0x00000000 in ?? () #1 0xad445f70 in ?? () #2 0x08058f44 in redisProcessCallbacks (ac=0xad445f70) at hiredis/async.c:403 #3 0x08059109 in redisAsyncHandleRead (ac=0xad445f70) at hiredis/async.c:467

#4 0x0804fbe0 in redisLibeventReadEvent (fd=378, event=2, arg=0xad45fb98) at ./hiredis/adapters/libevent.h:15
#5 0xb773fce9 in event_base_loop () from /usr/lib/libevent-2.0.so.5
#6 0xb7740a83 in event_base_dispatch () from /usr/lib/libevent-2.0.so.5

#7 0x0804a656 in worker_main (p=0x97291f0) at worker.c:156
#8 0xb771ed4c in start_thread () from /lib/i386-linux-gnu/tls/i686/nosegneg/libpthread.so.0
#9 0xb765dace in clone () from /lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6

Starting webdis with ulimit -c 60000
"http_port": 80,
"threads": 20,
"pool_size": 5,

Redis 2.4.7 is on another machine.

Thank you in advance.

Make fails with a message: "ls: can't access /usr/lib/libmsgpack.so"

I tried to build webdis but it requires msgpack though repository doesn't contains msgpack related source code.

% make clean all
ls: /usr/lib/libmsgpack.soにアクセスできません: No such file or directory
rm -f webdis.o cmd.o worker.o slog.o server.o libb64/cencode.o acl.o md5/md5.o http.o client.o websocket.o pool.o conf.o formats/json.o formats/raw.o formats/common.o formats/custom-type.o formats/bson.o hiredis/hiredis.o hiredis/sds.o hiredis/net.o hiredis/async.o jansson/src/dump.o jansson/src/error.o jansson/src/hashtable.o jansson/src/load.o jansson/src/strbuffer.o jansson/src/utf.o jansson/src/value.o jansson/src/variadic.o http-parser/http_parser.o webdis
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -DMSGPACK=0 -o webdis.o webdis.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -DMSGPACK=0 -o cmd.o cmd.c
In file included from cmd.c:14:
formats/msgpack.h:4:21: error: msgpack.h: No such file or directory
make: *** [cmd.o] エラー 1

truncates the key to the last dot.

I have dots in my keys, and webdis cuts the key from the last dot. I can workaround the request by appending something after my key, but it's annoying a little.

Add param "filename" to allow for nice looking filenames

http://www.ietf.org/rfc/rfc1806.txt

Using the content-disposition header with value of "attachment; filename=param[filename]" then requests that look like this

/GET/acme_inc:awesome_report:19:pdf.pdf?type=application/pdf&filename=awesome_report_20110506.pdf

in a browser are saved as "awesome_report_20110506.pdf" instead of "acme_inc:awesome_report:19:pdf.pdf"
also by making it an attachment the browser prompts to save/open rather than using the pdf plugin to render the pdf in the current tab (in this example, request in a browser)

whatcha think?

edit: I currently use this in a sinatra project...
http://rubydoc.info/gems/sinatra/1.2.6/Sinatra/Helpers:send_file
http://rubydoc.info/gems/sinatra/1.2.6/Sinatra/Helpers:attachment

send_file("/location/of/file/unique_id.pdf", {:filename => "quote.pdf"})

Question Mark in Value Escapes Premature

Steps to Reproduce:

POST LPUSH/key/{"zero": "zero?", "one": "one", "two": "two"}

{"LPUSH":1}

GET LPOP/key

{"LPOP":"{"zero": "zero"}

Remove the '?' things are good and it does not escape the string.

acl not working

hi,

i'm trying to block all commands except for a certain username and password, this acl blocked everything:
{
"disabled": ["*"]
},
{
"http_basic_auth": "test:test",
"enabled": ["PUBLISH"]
}

i couldn't publish anywhere.

websockets test not working at all

When testing the webdis build of "Jul 1 22:41:04 2012" with Redis 2.5.11 on Ubuntu 11.04 I've found that the websockets tests doesn't work at all.

Running the websocket test gives this result:

$> ./websocket  -v
ret=0
ret=0
ret=0
ret=0
No message was read.

Opening the websocket.html page shows the "loading" message but nothing happens.

Other tests work fine, so I don't believe it has to do with redis itself and, to the extend of what I understand of webdis, the websocket in a fully webdis side mechanism, which doesn't rely on any redis support.

Regards

Pablo

Failing to compile webdis on Mac OSX Lion

$ make clean all
rm -f webdis.o cmd.o worker.o slog.o server.o libb64/cencode.o acl.o md5/md5.o sha1/sha1.o http.o client.o websocket.o pool.o conf.o formats/json.o formats/raw.o formats/common.o formats/custom-type.o formats/bson.o hiredis/hiredis.o hiredis/sds.o hiredis/net.o hiredis/async.o jansson/src/dump.o jansson/src/error.o jansson/src/hashtable.o jansson/src/load.o jansson/src/strbuffer.o jansson/src/utf.o jansson/src/value.o jansson/src/variadic.o http-parser/http_parser.o webdis
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o webdis.o webdis.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o cmd.o cmd.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o worker.o worker.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o slog.o slog.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o server.o server.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o libb64/cencode.o libb64/cencode.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o acl.o acl.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o md5/md5.o md5/md5.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o sha1/sha1.o sha1/sha1.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o http.o http.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o client.o client.c
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o websocket.o websocket.c
websocket.c:18:20: error: endian.h: No such file or directory
websocket.c: In function ‘ws_parse_data’:
websocket.c:255: warning: implicit declaration of function ‘be64toh’
websocket.c: In function ‘ws_reply’:
websocket.c:331: warning: implicit declaration of function ‘htobe64’
make: *** [websocket.o] Error 1

Any thoughts?

Half-Open Connections Problems

when client crash or network broken,webdis also keep the connection established for 20 hours.According TCPIP Protocal, webdis should send KeepAlive probe package to detect this,but tcpdump didn't capture this package.

webdis server tcpdump
linux-191:~/nicolasff-webdis-8a8ab84 # tcpdump -i eth0 host 10.0.64.10 and port 7379
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
09:10:30.161126 IP 10.0.64.10.40770 > linux-191.site.7379: S 272338310:272338310(0) win 5840 <mss 1460,sackOK,timestamp 167148473 0,nop,wscale 7>
09:10:30.161155 IP linux-191.site.7379 > 10.0.64.10.40770: S 652998709:652998709(0) ack 272338311 win 5792 <mss 1460,sackOK,timestamp 151672290 167148473,nop,wscale 7>
09:10:30.161495 IP 10.0.64.10.40770 > linux-191.site.7379: . ack 1 win 46 <nop,nop,timestamp 167148473 151672290>
09:10:30.200643 IP 10.0.64.10.40770 > linux-191.site.7379: P 1:257(256) ack 1 win 46 <nop,nop,timestamp 167148483 151672290>
09:10:30.200655 IP linux-191.site.7379 > 10.0.64.10.40770: . ack 257 win 54 <nop,nop,timestamp 151672300 167148483>
09:10:30.338561 IP linux-191.site.7379 > 10.0.64.10.40770: P 1:267(266) ack 257 win 54 <nop,nop,timestamp 151672334 167148483>
09:10:30.338976 IP 10.0.64.10.40770 > linux-191.site.7379: . ack 267 win 54 <nop,nop,timestamp 167148517 151672334>

11:15:30.267179 IP 10.0.64.10.40770 > linux-191.site.7379: P 257:513(256) ack 267 win 54 <nop,nop,timestamp 169023520 151672334>
11:15:30.267209 IP linux-191.site.7379 > 10.0.64.10.40770: . ack 513 win 62 <nop,nop,timestamp 153547316 169023520>
11:15:30.392543 IP linux-191.site.7379 > 10.0.64.10.40770: P 267:533(266) ack 513 win 62 <nop,nop,timestamp 153547348 169023520>
11:15:30.392908 IP 10.0.64.10.40770 > linux-191.site.7379: . ack 533 win 63 <nop,nop,timestamp 169023552 153547348>
13:20:30.363517 IP 10.0.64.10.40770 > linux-191.site.7379: P 513:769(256) ack 533 win 63 <nop,nop,timestamp 170898565 153547348>
13:20:30.363541 IP linux-191.site.7379 > 10.0.64.10.40770: . ack 769 win 71 <nop,nop,timestamp 155422340 170898565>
13:20:30.497825 IP linux-191.site.7379 > 10.0.64.10.40770: P 533:799(266) ack 769 win 71 <nop,nop,timestamp 155422374 170898565>
13:20:30.498587 IP 10.0.64.10.40770 > linux-191.site.7379: . ack 799 win 71 <nop,nop,timestamp 170898599 155422374>

at 14:00 network broken.

thanks for your help.

how to improve webdis concurrent performance per second

Hardware environment
:DELL 2950 8 CORE 8G RAM

Run REDIS-benchmark

====== PING_INLINE ======

33222.59 requests per second

====== PING_BULK ======

33444.82 requests per second

====== SET ======

39682.54 requests per second

====== GET ======

34965.04 requests per second

====== INCR ======

38610.04 requests per second

====== LPUSH ======

36764.70 requests per second

====== LPOP ======

34843.21 requests per second

====== SADD ======

37878.79 requests per second

====== SPOP ======

33783.79 requests per second

====== LPUSH (needed to benchmark LRANGE) ======

34129.69 requests per second

====== MSET (10 keys) ======

23584.91 requests per second

We use webdis proxy to operate REDIS through http request

Test tool webbench

setsid webbench -c 100 -t 60 http://111.1.3.68:7379/INCR/newcount
setsid webbench -c 200 -t 60 http://111.1.3.68:7379/INCR/newcount
Finally we read the newcount value to statistic the count of operations.
We have increased the concurrent client computers but it has nothing to do with the final result.
We use mutiple clients attack one server, it doesn't affect the result, either.

The operating counts per second are about 17000.
The same as the LPUSH or LPOP operation.

the config file of WEBDIS
{
"redis_host": "127.0.0.1",

"redis_port":   6379,
"redis_auth":   null,

"http_host":    "0.0.0.0",
"http_port":    7379,
"threads":  8,

"daemonize":    false,
"websockets":   false,

"database": 0,

"acl": [
    {
        "disabled": ["DEBUG" , "FLUSHDB", "FLUSHALL"]
    },

    {
        "http_basic_auth":  "user:password",
        "enabled":      ["DEBUG"]
    }
],

    "verbosity": 3,
    "logfile": "webdis.log"

}

Now I want to seek help about how to improve webdis concurrent performance per second from you. How we can modify this system so the performance can approach to the result by RERDIS-BENCHMARK?

Google Chrome 14/15 websocket not supported

The following javascript works fine on my Google Chrome 12 and Chromium 13 (Ubuntu 64bits).
It fails with Chrome 14 and Chrome 15 : the onopen() callback is never triggered.

    function testJSON() {
        jsonSocket = new WebSocket("ws://127.0.0.1:7379/.json");
        jsonSocket.onopen = function() {
            console.log("JSON socket connected!");
            jsonSocket.send(JSON.stringify(["SET", "hello", "world"]))
            jsonSocket.send(JSON.stringify(["GET", "hello"]))
        }
        jsonSocket.onmessage = function(messageEvent) {
            console.log("JSON received:", messageEvent.data)
        }        
    }
    testJSON();  

EADDRNOTAVAIL when trying to bind to 127.0.0.1 on Snow Leopard

I assume it would fail on any other address, but I was just attempting to bind to loopback. I also assume it will (eventually, but that depends on the compiler, on defaults, on fallbacks, on magic numbers...) fail on other BSDs.

Two things solved it for me. One was bzero-ing the whole struct sockaddr_in (which is standard practice), the other was filling in sin_len. You will need to #ifdef filling sin_len as not every OS sports this field, but all the BSDs do, as far as I can tell.

"Works-for-me" patch follows.

diff --git a/server.c b/server.c
index 8b85519..0aed41c 100644
--- a/server.c
+++ b/server.c
@@ -25,10 +25,12 @@ socket_setup(const char *ip, short port) {
    struct sockaddr_in addr;
    int fd, ret;

+   bzero(&addr, sizeof(addr));
+   addr.sin_len = sizeof(struct sockaddr_in);
+
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);

-   memset(&(addr.sin_addr), 0, sizeof(addr.sin_addr));
    addr.sin_addr.s_addr = inet_addr(ip);

    /* this sad list of tests could use a Maybe monad... */

correct key - HTTP/1.1 200 OK

Hello!
Happy New Year! I wish you success!
Do I do not understand.
Tell me how to do that properly I would get a HTTP/1.1 200 OK, only on request with the correct key
I do so:
Console check for entries:
# redis-cli keys '*'
1) example: mydata: 558255808376

to make http request: by doing this query:
http://192.168.0.90:7379/get/example:data:558255808376 -> response: HTTP/1.1 200 OK

http://192.168.0.90:7379/get/example:data:558255808376 -> HTTP/1.1 304 Not Modified - this is a second request to the existing record but returns a response 304

http://192.168.0.90:7379/get/example:data:558255808376.txt -> response: HTTP/1.1 200 OK

http://192.168.0.90:7379/get/example:data:558255808376.txt11111 -> response: HTTP/1.1 200 OK - we can change arbitrarily, but I still get 200

http://192.168.0.90:7379/get/ -> response: HTTP/1.1 200 OK - it turns out that, in any case, what is the response we get.

I hope that I could understand the idea explained to.
Thank you for the answer!

Build is failing on Mac OS X Lion 7.3

$ make
cc -c -O3 -Wall -Wextra -I. -Ijansson/src -Ihttp-parser -o webdis.o webdis.c
In file included from webdis.c:1:
./server.h:4:10: fatal error: 'event.h' file not found

include <event.h>

     ^

1 error generated.
make: *** [webdis.o] Error 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.