ring-clojure / ring-clojure/ring

Add protocol for handling Request & Response

Open
#372 7 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Clojure
Stars
3.9k
Forks
528
PR merge metrics
No merged PRs in 30d

Description

Many modern Java Web Server (Netty, Undertow, Vert.x) have their own abstractions for Requests and Responses. Current ring-spec states that requests and responses as map-like structures. While this is awesome in abstraction-wise (and the killer feature of Ring), performance-wise it can be bad as data needs to be copied into maps. Copying can be eager (like with the jetty-adapter) for all requests or lazy (like Aleph & Immutant) / on demand, but still things like accessing a single header value forced all headers to be read copied and keys lowercased.

Abstracting the request and response as protocols would allow best of both worlds. A protocol like:

(defprotocol RingRequest
  (get-server-port [this])
  (get-server-name [this])
  (get-remote-addr [this])
  (get-uri [this])
  (get-query-string [this])
  (get-scheme [this])
  (get-request-method [this])
  (get-protocol [this])
  (get-headers [this])
  (get-header [this header])
  (get-body [this])
  (get-context [this]))

could be implemented for maps so that they do the normal lookup, but the Aleph-style zero-copy-request (map-like) classes could implement those directly. (get-header request "Content-Type") would use the already parsed information without any copying.

This would allow low-level libraries to be programmed against effective protocols while keeping everything compatible with maps.

Currently working on a new lightweight and zero-fat new wrapper for Undertow and using a custom request protocol (like the one above) with it, but would not like to tie our other libraries to a server-specific protocols.

All the current web servers having their own request & response (map-like) types would need to conform to the new protocols, so would be a breaking change.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the current ring-spec and the request/response handling in the Jetty adapter, Aleph, and Immutant mentioned in the issue. Compare those interfaces with the proposed RingRequest protocol and the Undertow wrapper context. Done would require an agreed protocol design, compatible implementations for existing server types, and a documented plan for the breaking change.

Written by the indexing model from the issue text.

Assessment

Tech stack
clojure
Domain
api, backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.