{"id":13392865,"url":"https://github.com/nicolasff/webdis","last_synced_at":"2025-05-14T00:06:20.257Z","repository":{"id":1246205,"uuid":"1184678","full_name":"nicolasff/webdis","owner":"nicolasff","description":"A Redis HTTP interface with JSON output","archived":false,"fork":false,"pushed_at":"2025-03-14T15:10:14.000Z","size":1156,"stargazers_count":2880,"open_issues_count":66,"forks_count":308,"subscribers_count":124,"default_branch":"master","last_synced_at":"2025-04-10T02:16:49.655Z","etag":null,"topics":["http","json","redis","webdis","websocket"],"latest_commit_sha":null,"homepage":"https://webd.is","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nicolasff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2010-12-20T16:17:29.000Z","updated_at":"2025-04-09T23:00:22.000Z","dependencies_parsed_at":"2023-07-05T19:49:07.682Z","dependency_job_id":"5bf48d03-f037-4f29-b820-9362a3a1f541","html_url":"https://github.com/nicolasff/webdis","commit_stats":{"total_commits":563,"total_committers":31,"mean_commits":"18.161290322580644","dds":"0.24689165186500883","last_synced_commit":"5eece3733313221dcfcd3710591b7a8bd15d9f30"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasff%2Fwebdis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasff%2Fwebdis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasff%2Fwebdis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasff%2Fwebdis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nicolasff","download_url":"https://codeload.github.com/nicolasff/webdis/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248142907,"owners_count":21054672,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["http","json","redis","webdis","websocket"],"created_at":"2024-07-30T17:00:38.361Z","updated_at":"2025-04-10T02:16:57.733Z","avatar_url":"https://github.com/nicolasff.png","language":"C","readme":"[![Build](https://github.com/nicolasff/webdis/actions/workflows/build.yml/badge.svg)](https://github.com/nicolasff/webdis/actions/workflows/build.yml)\n\n\n# About Webdis\n\nA very simple web server providing an HTTP interface to Redis. It embeds [hiredis](https://github.com/antirez/hiredis), [jansson](https://github.com/akheron/jansson) (with some [local changes](./src/jansson/WEBDIS-CHANGES.md)), and [http-parser](https://github.com/ry/http-parser/). It also depends on [libevent](https://monkey.org/~provos/libevent/), to be installed separately.\n\n# Build and run from source\n\nBuilding Webdis requires the libevent development package. You can install it on Ubuntu by typing `sudo apt-get install libevent-dev` or on macOS by typing `brew install libevent`.\n\nTo build Webdis with support for encrypted connections to Redis, see [Building Webdis with SSL support](#building-webdis-with-ssl-support).\n\n```sh\n$ make clean all\n\n$ ./webdis \u0026\n\n$ curl http://127.0.0.1:7379/SET/hello/world\n→ {\"SET\":[true,\"OK\"]}\n\n$ curl http://127.0.0.1:7379/GET/hello\n→ {\"GET\":\"world\"}\n\n$ curl -d \"GET/hello\" http://127.0.0.1:7379/\n→ {\"GET\":\"world\"}\n```\n\n## Configuration\n\nWebdis is configured by a configuration file in JSON format, provided to the server as a command-line parameter:\n```sh\n./webdis /path/to/webdis.json\n```\n\nAt start-up, Webdis will look for a file named `webdis.json` in the current directory if no file is specified on the command line.\n\nThis 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.\n\nThe various features of Webdis are documented in this README.\n\n# Try in Docker\n\n```sh\n$ docker run --name webdis-test --rm -d -p 127.0.0.1:7379:7379 nicolas/webdis\n0d2ce311a4834d403cc3e7cfd571b168ba40cede6a0e155a21507bb0bf7bee81\n\n$ curl http://127.0.0.1:7379/PING\n{\"PING\":[true,\"PONG\"]}\n\n# To stop it:\n$ docker stop webdis-test\n0d2ce311a483\n```\n\n## Docker repositories and Docker Content Trust\n\nWebdis images are published on [Docker Hub](https://hub.docker.com/r/nicolas/webdis) and [Amazon ECR](https://gallery.ecr.aws/nicolas/webdis).\n\n### Docker Hub\n\n```sh\n$ docker pull nicolas/webdis:0.1.22\n$ docker pull nicolas/webdis:latest\n```\nStarting from release `0.1.12` and including `latest`, Docker Hub images are signed ([download public key](nicolasff.pub)). You should see the following key ID if you verify the trust:\n\n```\n$ docker trust inspect nicolas/webdis:0.1.22 --pretty\n\nSignatures for nicolas/webdis:0.1.22\n\nSIGNED TAG   DIGEST                                                             SIGNERS\n0.1.22       5a7d342e3a9e5667fe05f045beae4b5042681d1d737f60843b7dfd11f96ab72f   (Repo Admin)\n\nList of signers and their keys for nicolas/webdis:0.1.22\n\nSIGNER      KEYS\nnicolasff   dd0768b9d35d\n\nAdministrative keys for nicolas/webdis:0.1.22\n\n  Repository Key:\tfed0b56b8a8fd4d156fb2f47c2e8bd3eb61948b72a787c18e2fa3ea3233bba1a\n  Root Key:\t40be21f47831d593892370a8e3fc5bfffb16887c707bd81a6aed2088dc8f4bef\n```\n\nThe signing keys are listed on [this documentation page](docs/webdis-docker-content-trust.md#-key-ids); please make sure they match what you see.\nThe same documentation page details how to [verify the signatures of multi-architecture images](docs/webdis-docker-content-trust.md), and the tree of manifests used to build them.\n\n### Amazon Elastic Container Registry (ECR)\n\n```sh\n$ docker pull public.ecr.aws/nicolas/webdis:0.1.22\n$ docker pull public.ecr.aws/nicolas/webdis:latest\n```\n\n**A note on ECR and trust:** [AWS does not support Notary v2](https://github.com/aws/containers-roadmap/issues/43) at the time of this writing, although [a security talk from 2020](https://d2908q01vomqb2.cloudfront.net/fe2ef495a1152561572949784c16bf23abb28057/2020/08/21/C3-ECR-Security-Best-Practices_072020_v3-no-notes.pdf#page=19) mentions that the feature could be available in 2021.\n\nThe consequence is that [Webdis images on ECR](https://gallery.ecr.aws/nicolas/webdis) are not signed at this time.\n\nThey 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.\n\nFor more details about Content Trust validation with ECR images, refer to the article titled [Webdis and Docker Content Trust](docs/webdis-docker-content-trust.md) in the [Webdis documentation](docs/README.md).\n\n## Multi-architecture images\n\nStarting with [release 0.1.19](https://github.com/nicolasff/webdis/releases/tag/0.1.19), Docker images for Webdis are published as [manifest lists](https://docs.docker.com/registry/spec/manifest-v2-2/#media-types) supporting [multiple architectures](https://docs.docker.com/desktop/multi-arch/). Each release points to an x86-64 image and an ARM64v8 image:\n\n```\n$ docker manifest inspect nicolas/webdis:0.1.19 | jq -r '.manifests | .[] | .platform.architecture + \" -\u003e \" + .digest'\namd64 -\u003e sha256:2ced2d99146e1bcaf10541d17dbac573cffd02237c3b268875be1868138d3b54\narm64 -\u003e sha256:d026c5675552947b6a755439dfd58360e44a8860436f4eddfe9b26d050801248\n```\n\nBy default `docker pull` will download only the relevant image for your architecture, but you can [specify the platform](https://docs.docker.com/engine/reference/commandline/pull/) to download the image for a specific architecture, e.g.\n```\n$ docker pull nicolas/webdis:0.1.19 --platform linux/arm64/v8\n```\n\n# Build and run a Docker image locally\n\nClone the repository and open a terminal in the webdis directory, then run:\n```sh\n$ docker build -t webdis:custom .\n[...]\n\n$ docker run --name webdis-test --rm -d -p 127.0.0.1:7379:7379 webdis:custom\nf0a2763fd456ac1f7ebff80eeafd6a5cd0fc7f06c69d0f7717fb2bdcec65926e\n\n$ curl http://127.0.0.1:7379/PING\n{\"PING\":[true,\"PONG\"]}\n```\n\nTo stop it:\n```\n$ docker stop webdis-test\nf0a2763fd456\n```\n\n## Docker images and embedded Redis\n\n:information_source: The Docker images [provided on Docker Hub](https://hub.docker.com/r/nicolas/webdis) under `nicolas/webdis` contain both Webdis and an embedded Redis server. They were built this way to make it easy to [try Webdis](#try-in-docker) without having to configure a Docker deployment with two containers, but this is likely not the best way to run Webdis in production.\n\nThe following documentation pages cover various such use cases:\n- [Running Webdis in Docker with an external Redis instance](docs/webdis-docker-external-redis.md)\n- [Running Webdis and Redis in Docker Compose](docs/webdis-redis-docker-compose.md)\n- [Running Webdis and Redis in Docker Compose with SSL connections](docs/webdis-redis-docker-compose-ssl.md)\n\nMore articles are available in the [Webdis documentation](docs/README.md).\n\n\n# Building Webdis with SSL support\n\nWebdis needs libraries that provide TLS support to encrypt its connections to Redis:\n\n* On Alpine Linux, install `openssl-dev` with `apk-add openssl-dev`.\n* On Ubuntu, install `libssl-dev` with `apt-get install libssl-dev`.\n* On macOS with HomeBrew, install OpenSSL with `brew install openssl@1.1`.\n\nThen, build Webdis with SSL support enabled:\n\n```sh\n$ make SSL=1\n```\n\n# Configuring Webdis with SSL\n\nOnce Redis is configured with SSL support (see [this guide](https://nishanths.svbtle.com/setting-up-redis-with-tls) for step-by-step instructions), you can configure Webdis to connect to Redis over encrypted connections.\n\nAdd a block to `webdis.json` under a key named `\"ssl\"` placed at the root level, containing the following object:\n\n```json\n{\n    \"enabled\": true,\n    \"ca_cert_bundle\": \"/path/to/ca.crt\",\n    \"path_to_certs\": \"/path/to/trusted/certs\",\n    \"client_cert\": \"/path/to/redis.crt\",\n    \"client_key\": \"/path/to/redis.key\",\n    \"redis_sni\": \"redis.mydomain.tld\"\n}\n```\nThis means that `\"ssl\"` should be at the same level as `\"redis_host\"`, `\"redis_port\"`, etc.\n\n**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.\n\nUse the following table to match the Redis configuration keys to the fields under `\"ssl\"` in `webdis.json`:\n\n| Redis field        | Webdis field     | Purpose               |\n| ------------------ | ---------------- | --------------------- |\n| `tls-cert-file`    | `client_cert`    | Client certificate    |\n| `tls-key-file`     | `client_key`     | Client key            |\n| `tls-ca-cert-file` | `ca_cert_bundle` | CA certificate bundle |\n\nTwo other keys have no equivalent in `redis.conf`:\n\n- `path_to_certs` is an optional directory path where trusted CA certificate files are stored in an OpenSSL-compatible format.\n- `redis_sni` is an optional Redis server name, used as a server name indication (SNI) TLS extension.\n\nSee also the [Hiredis docs](https://github.com/redis/hiredis/blob/v1.0.2/README.md#hiredis-openssl-wrappers) and [Hiredis source code](https://github.com/redis/hiredis/blob/v1.0.2/hiredis_ssl.h#L77-L96) for more information.\n\n\n### Running Redis and Webdis with SSL in Docker Compose\n\nFor 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 \u0026 Redis in Docker Compose with SSL connections](docs/webdis-redis-docker-compose-ssl.md).\n\n## SSL troubleshooting\n\nFollow this table to diagnose issues with SSL connections to Redis.\n\n| Error message or issue | Cause | Solution |\n| ---------------------- | ----- | -------- |\n| Unexpected key or incorrect value in `webdis.json`: 'ssl' | Webdis is not compiled with SSL support | Build webdis with `make SSL=1` |\n| 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 |\n| Failed to load client certificate | Invalid client certificate | Verify the file that `client_cert` points to |\n| Failed to load private key | Invalid client key | Verify the file that `client_key` points to |\n| Failed to load CA Certificate or CA Path | Invalid CA certificate bundle | Verify the file that `ca_cert_bundle` points to |\n| 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 |\n| 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. |\n| 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` |\n\n\n# Features\n* `GET` and `POST` are supported, as well as `PUT` for file uploads (see example of `PUT` usage [here](#file-upload)).\n* JSON output by default, optional JSONP parameter (`?jsonp=myFunction` or `?callback=myFunction`).\n* Raw Redis 2.0 protocol output with `.raw` suffix.\n* MessagePack output with `.msg` suffix.\n* HTTP 1.1 pipelining (70,000 http requests per second on a desktop Linux machine.)\n* Multi-threaded server, configurable number of worker threads.\n* [WebSocket support](#websockets) (Currently using the specification from [RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455)).\n* Connects to Redis using a TCP or UNIX socket.\n* Support for [secure connections to Redis](#configuring-webdis-with-ssl) (requires [Redis 6 or newer](https://redis.io/topics/encryption)).\n* 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](https://github.com/redis/hiredis/tree/e07ae7d3b6248be8be842eca3e1e97595a17aa1a#other-configuration-using-socket-options) 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`).\n* Restricted commands by IP range (CIDR subnet + mask) or HTTP Basic Auth, returning 403 errors.\n* 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](https://redis.io/commands/auth)).\n* Environment variables can be used as values in the config file, starting with `$` and in all caps (e.g. `$REDIS_HOST`).\n* Pub/Sub using `Transfer-Encoding: chunked`, works with JSONP as well. Webdis can be used as a Comet server.\n* Drop privileges on startup.\n* Custom Content-Type using a pre-defined file extension, or with `?type=some/thing`.\n* URL-encoded parameters for binary data or slashes and question marks. For instance, `%2f` is decoded as `/` but not used as a command separator.\n* Logs, with a configurable verbosity.\n* Configurable `fsync` frequency for the log file:\n    * Set `\"log_fsync\": \"auto\"` (default) to let the file system handle file persistence on its own.\n    * Set `\"log_fsync\": N` where `N` is a number to call `fsync` every `N` milliseconds.\n    * Set `\"log_fsync\": \"all\"` (very slow) to persist the log file to its storage device on each log message.\n* Cross-origin requests, usable with XMLHttpRequest2 (Cross-Origin Resource Sharing - CORS).\n* [File upload](#file-upload) with `PUT`.\n* With the JSON output, the return value of INFO is parsed and transformed into an object.\n* Optionally run as a daemon process: set `\"daemonize\": true` and `\"pidfile\": \"/var/run/webdis.pid\"` in `webdis.json`.\n* Default root object: Add `\"default_root\": \"/GET/index.html\"` in `webdis.json` to substitute the request to `/` with a Redis request.\n* HTTP request limit with `http_max_request_size` (in bytes, set to 128 MB by default).\n* Database selection in the URL, using e.g. `/7/GET/key` to run the command on DB 7.\n\n# Ideas, TODO…\n* Add better support for PUT, DELETE, HEAD, OPTIONS? How? For which commands?\n    * 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.\n* MULTI/EXEC/DISCARD/WATCH are disabled at the moment; find a way to use them.\n* Support POST of raw Redis protocol data, and execute the whole thing. This could be useful for MULTI/EXEC transactions.\n* Enrich config file:\n    * Provide timeout (maybe for some commands only?). What should the response be? 504 Gateway Timeout? 503 Service Unavailable?\n* Multi-server support, using consistent hashing.\n* SSL/TLS?\n    * It makes more sense to terminate SSL with nginx used as a reverse-proxy.\n* SPDY?\n    * SPDY is mostly useful for parallel fetches. Not sure if it would make sense for Webdis.\n* Send your ideas using the github tracker, on twitter [@yowgi](https://twitter.com/yowgi) or by e-mail to n.favrefelix@gmail.com.\n\n# HTTP error codes\n* Unknown HTTP verb: 405 Method Not Allowed.\n* Redis is unreachable: 503 Service Unavailable.\n* Matching ETag sent using `If-None-Match`: 304 Not Modified.\n* Could also be used:\n    * Timeout on the redis side: 503 Service Unavailable.\n    * Missing key: 404 Not Found.\n    * Unauthorized command (disabled in config file): 403 Forbidden.\n\n# Command format\nThe URI `/COMMAND/arg0/arg1/.../argN.ext` executes the command on Redis and returns the response to the client. GET, POST, and PUT are supported:\n\n* `GET /COMMAND/arg0/.../argN.ext`\n* `POST /` with `COMMAND/arg0/.../argN` in the HTTP body.\n* `PUT /COMMAND/arg0.../argN-1` with `argN` in the HTTP body (see section on [file uploads](#file-upload).)\n\n`.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).\n\nSpecial characters: `/` and `.` have special meanings, `/` separates arguments and `.` changes the Content-Type. They can be replaced by `%2f` and `%2e`, respectively.\n\n# Redis authentication\n\nWebdis can connect to a Redis server that requires credentials.\nFor Redis versions before 6.0, provide the password as a single string in `webdis.json` using the key `\"redis_auth\"`. For example:\n```json\n    \"redis_auth\": \"enter-password-here\"\n```\nRedis 6.0 introduces a more granular [access control system](https://redis.io/topics/acl) 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.\n```json\n    \"redis_auth\": [\"my-username\", \"my-password\"]\n```\nThis new authentication system is only supported in Webdis 0.1.13 and above.\n\n# ACL\nAccess control is configured in `webdis.json`. Each configuration tries to match a client profile according to two criteria:\n\n* [CIDR](https://en.wikipedia.org/wiki/CIDR) subnet + mask\n* [HTTP Basic Auth](https://en.wikipedia.org/wiki/Basic_access_authentication) in the format of \"user:password\".\n\nEach 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.\n\nExamples:\n```json\n{\n    \"disabled\": [\"DEBUG\", \"FLUSHDB\", \"FLUSHALL\"],\n},\n\n{\n    \"http_basic_auth\": \"user:password\",\n    \"disabled\":        [\"DEBUG\", \"FLUSHDB\", \"FLUSHALL\"],\n    \"enabled\":         [\"SET\"]\n},\n\n{\n    \"ip\":      \"192.168.10.0/24\",\n    \"enabled\": [\"SET\"]\n},\n\n{\n    \"http_basic_auth\": \"user:password\",\n    \"ip\":              \"192.168.10.0/24\",\n    \"enabled\":         [\"SET\", \"DEL\"]\n}\n```\nACLs are interpreted in order, later authorizations superseding earlier ones if a client matches several. The special value \"*\" matches all commands.\n\n## ACLs and Websocket clients\n\nThese rules apply to WebSocket connections as well, although without support for HTTP Basic Auth filtering. IP filtering is supported.\n\nFor JSON-based WebSocket clients, a rejected command will return this object (sent as a string in a binary frame):\n```json\n{\"message\": \"Forbidden\", \"error\": true, \"http_status\": 403}\n```\nThe `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.\n\nFor raw Redis protocol WebSocket clients, a rejected command will produce this error (sent as a string in a binary frame):\n```\n-ERR Forbidden\\r\\n\n```\n\n# Environment variables\n\nEnvironment variables can be used in `webdis.json` to read values from the environment instead of using constant values.\nFor 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:\n\n```json\n{\n    \"redis_host\": \"$REDIS_HOST\",\n    \"redis_port\": \"$REDIS_PORT\",\n}\n```\n\n# JSON output\nJSON is the default output format. Each command returns a JSON object with the command as a key and the result as a value.\n\n**Examples:**\n```sh\n// string\n$ curl http://127.0.0.1:7379/GET/y\n{\"GET\":\"41\"}\n\n// number\n$ curl http://127.0.0.1:7379/INCR/y\n{\"INCR\":42}\n\n// list\n$ curl http://127.0.0.1:7379/LRANGE/x/0/1\n{\"LRANGE\":[\"abc\",\"def\"]}\n\n// status\n$ curl http://127.0.0.1:7379/TYPE/y\n{\"TYPE\":[true,\"string\"]}\n\n// error, which is basically a status\n$ curl http://127.0.0.1:7379/MAKE-ME-COFFEE\n{\"MAKE-ME-COFFEE\":[false,\"ERR unknown command 'MAKE-ME-COFFEE'\"]}\n\n// JSONP callback:\n$ curl  \"http://127.0.0.1:7379/TYPE/y?jsonp=myCustomFunction\"\nmyCustomFunction({\"TYPE\":[true,\"string\"]})\n```\n\n# RAW output\nThis is the raw output of Redis; enable it with the `.raw` suffix.\n```sh\n// string\n$ curl http://127.0.0.1:7379/GET/z.raw\n$5\nhello\n\n// number\n$ curl http://127.0.0.1:7379/INCR/a.raw\n:2\n\n// list\n$ curl http://127.0.0.1:7379/LRANGE/x/0/-1.raw\n*2\n$3\nabc\n$3\ndef\n\n// status\n$ curl http://127.0.0.1:7379/TYPE/y.raw\n+zset\n\n// error, which is basically a status\n$ curl http://127.0.0.1:7379/MAKE-ME-COFFEE.raw\n-ERR unknown command 'MAKE-ME-COFFEE'\n```\n\n# Custom content-type\nSeveral content-types are available:\n\n* `.json` for `application/json` (this is the default Content-Type).\n* `.msg` for `application/x-msgpack`. See [https://msgpack.org/](https://msgpack.org/) for the specs.\n* `.txt` for `text/plain`\n* `.html` for `text/html`\n* `.xhtml` for `application/xhtml+xml`\n* `.xml` for `text/xml`\n* `.png` for `image/png`\n* `.jpg` or `.jpeg` for `image/jpeg`\n* Any other with the `?type=anything/youwant` query string.\n* Add a custom separator for list responses with `?sep=,` query string.\n\n```\n$ curl -v \"http://127.0.0.1:7379/GET/hello.html\"\n[...]\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: text/html\n\u003c Date: Mon, 03 Jan 2011 20:43:36 GMT\n\u003c Content-Length: 137\n\u003c\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n[...]\n\u003c/html\u003e\n\n$ curl -v \"http://127.0.0.1:7379/GET/hello.txt\"\n[...]\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: text/plain\n\u003c Date: Mon, 03 Jan 2011 20:43:36 GMT\n\u003c Content-Length: 137\n[...]\n\n$ curl -v \"http://127.0.0.1:7379/GET/big-file?type=application/pdf\"\n[...]\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: application/pdf\n\u003c Date: Mon, 03 Jan 2011 20:45:12 GMT\n[...]\n```\n\n# File upload\nWebdis supports file upload using HTTP PUT. The command URI is slightly different, as the last argument is taken from the HTTP body.\nFor 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.\n\n**Uploading a binary file to webdis**:\n```\n$ file redis-logo.png\nredis-logo.png: PNG image, 513 x 197, 8-bit/color RGBA, non-interlaced\n\n$ wc -c redis-logo.png\n16744 redis-logo.png\n\n$ curl -v --upload-file redis-logo.png http://127.0.0.1:7379/SET/logo\n[...]\n\u003e PUT /SET/logo HTTP/1.1\n\u003e 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\n\u003e Host: 127.0.0.1:7379\n\u003e Accept: */*\n\u003e Content-Length: 16744\n\u003e Expect: 100-continue\n\u003e\n\u003c HTTP/1.1 100 Continue\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: application/json\n\u003c ETag: \"0db1124cf79ffeb80aff6d199d5822f8\"\n\u003c Date: Sun, 09 Jan 2011 16:48:19 GMT\n\u003c Content-Length: 19\n\u003c\n{\"SET\":[true,\"OK\"]}\n\n$ curl -vs http://127.0.0.1:7379/GET/logo.png -o out.png\n\u003e GET /GET/logo.png HTTP/1.1\n\u003e 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\n\u003e Host: 127.0.0.1:7379\n\u003e Accept: */*\n\u003e\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: image/png\n\u003c ETag: \"1991df597267d70bf9066a7d11969da0\"\n\u003c Date: Sun, 09 Jan 2011 16:50:51 GMT\n\u003c Content-Length: 16744\n\n$ md5sum redis-logo.png out.png\n1991df597267d70bf9066a7d11969da0  redis-logo.png\n1991df597267d70bf9066a7d11969da0  out.png\n```\n\nThe file was uploaded and re-downloaded properly: it has the same hash and the content-type was set properly thanks to the `.png` extension.\n\n# WebSockets\nWebdis supports WebSocket clients implementing [RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455).\n\n**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.\n\n```json\n{\n    \"daemonize\": false,\n    \"websockets\": true,\n}\n```\n(start and end of file omitted).\n\nWebSockets are supported with the following formats, selected by the connection URL:\n\n* JSON (on `/` or `/.json`)\n* Raw Redis wire protocol (on `/.raw`)\n\n**Example**:\n```javascript\nfunction testJSON() {\n    var jsonSocket = new WebSocket(\"ws://127.0.0.1:7379/.json\");\n    jsonSocket.onmessage = function(messageEvent) {\n        console.log(\"JSON received:\", messageEvent.data);\n    };\n    jsonSocket.onopen = function() {\n        console.log(\"JSON socket connected!\");\n        jsonSocket.send(JSON.stringify([\"SET\", \"hello\", \"world\"]));\n        jsonSocket.send(JSON.stringify([\"GET\", \"hello\"]));\n    };\n}\ntestJSON();\n```\n\nThis produces the following output:\n```\nJSON socket connected!\nJSON received: {\"SET\":[true,\"OK\"]}\nJSON received: {\"GET\":\"world\"}\n```\n\n## WebSockets HTML demo\n\nThe Webdis repository contains a demo web page with JavaScript code that can be used to test WebSocket support.\n\nIn a terminal, check out Webdis, build it, and configure it with WebSocket support:\n\n```shell\n$ cd ~/src/webdis\n$ make\n$ vim webdis.json      # (edit the file to add \"websockets\": true)\n$ grep websockets webdis.json\n    \"websockets\": true,\n$ ./webdis\n```\n\nThen go to the `tests/` directory and open `websocket.html` with a web browser.\n\n# Pub/Sub with chunked transfer encoding\nWebdis 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.\n\n**Example using XMLHttpRequest**:\n```javascript\nvar previous_response_length = 0\nxhr = new XMLHttpRequest()\nxhr.open(\"GET\", \"http://127.0.0.1:7379/SUBSCRIBE/hello\", true);\nxhr.onreadystatechange = checkData;\nxhr.send(null);\n\nfunction checkData() {\n    if(xhr.readyState == 3)  {\n        response = xhr.responseText;\n        chunk = response.slice(previous_response_length);\n        previous_response_length = response.length;\n        console.log(chunk);\n    }\n};\n```\n\nPublish messages to redis to see output similar to the following:\n```json\n{\"SUBSCRIBE\":[\"subscribe\",\"hello\",1]}\n{\"SUBSCRIBE\":[\"message\",\"hello\",\"some message\"]}\n{\"SUBSCRIBE\":[\"message\",\"hello\",\"some other message\"]} \n```\n","funding_links":[],"categories":["C","json","Higher level libraries and tools"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicolasff%2Fwebdis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnicolasff%2Fwebdis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicolasff%2Fwebdis/lists"}