Skip to content

Commit

Permalink
Merge branch 'main' into session_upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
SeanTAllen authored Mar 12, 2024
2 parents b22ef3e + a945455 commit d0d800e
Show file tree
Hide file tree
Showing 19 changed files with 419 additions and 156 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/breakage-against-ponyc-latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
run: make test ssl=0.9.0 config=debug
- name: Send alert on failure
if: ${{ failure() }}
uses: zulip/github-actions-zulip/send-message@b62d5a0e48a4d984ea4fce5dd65ba691963d4db4
uses: zulip/github-actions-zulip/send-message@08b6fbd07f5834e5b930a85bc7740e9fd44ab2e7
with:
api-key: ${{ secrets.ZULIP_SCHEDULED_JOB_FAILURE_API_KEY }}
email: ${{ secrets.ZULIP_SCHEDULED_JOB_FAILURE_EMAIL }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/changelog-bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Send alert on failure
if: ${{ failure() }}
uses: zulip/github-actions-zulip/send-message@b62d5a0e48a4d984ea4fce5dd65ba691963d4db4
uses: zulip/github-actions-zulip/send-message@08b6fbd07f5834e5b930a85bc7740e9fd44ab2e7
with:
api-key: ${{ secrets.ZULIP_SCHEDULED_JOB_FAILURE_API_KEY }}
email: ${{ secrets.ZULIP_SCHEDULED_JOB_FAILURE_EMAIL }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint-action-workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ jobs:
- name: Checkout
uses: actions/[email protected]
- name: Check workflow files
uses: docker://ghcr.io/ponylang/shared-docker-ci-actionlint:20230822
uses: docker://ghcr.io/ponylang/shared-docker-ci-actionlint:20240224
with:
args: -color
2 changes: 1 addition & 1 deletion .github/workflows/release-notes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
API_CREDENTIALS: ${{ secrets.GITHUB_TOKEN }}
- name: Send alert on failure
if: ${{ failure() }}
uses: zulip/github-actions-zulip/send-message@b62d5a0e48a4d984ea4fce5dd65ba691963d4db4
uses: zulip/github-actions-zulip/send-message@08b6fbd07f5834e5b930a85bc7740e9fd44ab2e7
with:
api-key: ${{ secrets.ZULIP_SCHEDULED_JOB_FAILURE_API_KEY }}
email: ${{ secrets.ZULIP_SCHEDULED_JOB_FAILURE_EMAIL }}
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ tags
/.coverage/
/_corral/
/_repos/
lock.json
lock.json
56 changes: 56 additions & 0 deletions .release-notes/0.5.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
## Ensure Content-Length is set for all Responses that need it

Previously responses without explicitly added Content-Length didn't add that header with a `0` value. This made some HTTP clients hang.
Now all responses built with this library will have a default `Content-Length` header set, unless marked with `Transfer-Encoding: chunked`

## Added `ResponseBuilderHeaders.set_content_length(content_length: USize)`

This way it is more convenient to set a content-length from a numeric value. E.g. from the size of a prepared array to be passed as HTTP body:

```pony
let body = "I am a teapot"
let response =
Responses.builder()
.set_status(StatusOK)
.set_content_length(body.size())
.add_header("Content-Type", "text/plain")
.finish_headers()
.add_chunk(body)
.build()
```

## Added `BuildableResponse.delete_header(header_name: String)`

Previously it was not possible to delete a header, once set it was permanent. No it is possible to delete a header e.g. in multi-stage processing of a HTTP response.

## `ResponseBuilderBody.add_chunk()` now takes a `ByteSeq` instead of `Array[U8] val`

This allows to pass `String val` as well as `Array[U8] val` to `add_chunk`.

```pony
let response = Responses.builder()
.set_content_length(7)
.finish_headers()
.add_chunk("AWESOME")
.build()
```

## `BuildableResponse.create()` now only takes a `Status` and optionally a `Version`

The logic applied to set `content_length` and `transfer_encoding` from the constructor parameters was a bit brittle, so it got removed. Use both `set_content_length(content_length: USize)` and `set_transfer_encoding(chunked: (Chunked | None))` to set them:

```pony
let body = "AWESOME"
let response = BuildableResponse
.create(StatusOK)
.set_content_length(body.size())
.set_header("Content-Type", "text/plain")
```

## `Response.transfer_coding()` changed to `.transfer_encoding()`

The wording now is now equal to the actual header name set with this method.

## `BuildableResponse.set_transfer_coding()` changed to `.set_transfer_encoding()`

Following the `Response` trait.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,24 @@ All notable changes to this project will be documented in this file. This projec
### Changed


## [0.5.0] - 2024-02-18

### Fixed

- Ensure Content-Length is set for all Responses that need it ([PR #74](https://github.com/ponylang/http_server/pull/74))

### Added

- Added `ResponseBuilderHeaders.set_content_length(content_length: USize)` ([PR #74](https://github.com/ponylang/http_server/pull/74))
- Added `BuildableResponse.delete_header(header_name: String)` ([PR #74](https://github.com/ponylang/http_server/pull/74))

### Changed

- `ResponseBuilderBody.add_chunk()` now takes a `ByteSeq` instead of `Array[U8] val` ([PR #74](https://github.com/ponylang/http_server/pull/74))
- `BuildableResponse.create()` now only takes a `Status` and a `Version` ([PR #74](https://github.com/ponylang/http_server/pull/74))
- `BuildableResponse.set_transfer_coding()` changed to `.set_transfer_encoding()` ([PR #74](https://github.com/ponylang/http_server/pull/74))
- `Response.transfer_coding()` changed to `.transfer_encoding()` ([PR #74](https://github.com/ponylang/http_server/pull/74))

## [0.4.6] - 2024-01-14

### Changed
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ config ?= release
PACKAGE := http_server
GET_DEPENDENCIES_WITH := corral fetch
CLEAN_DEPENDENCIES_WITH := corral clean
COMPILE_WITH := corral run -- ponyc
PONYC ?= ponyc
COMPILE_WITH := corral run -- $(PONYC)

BUILD_DIR ?= build/$(config)
SRC_DIR ?= $(PACKAGE)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Pony package to build server applications for the HTTP protocol.
## Installation

* Install [corral](https://github.com/ponylang/corral):
* `corral add github.com/ponylang/http_server.git --version 0.4.6`
* `corral add github.com/ponylang/http_server.git --version 0.5.0`
* Execute `corral fetch` to fetch your dependencies.
* Include this package by adding `use "http_server"` to your Pony sources.
* Execute `corral run -- ponyc` to compile your application
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.6
0.5.0
2 changes: 1 addition & 1 deletion corral.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"homepage": "https://github.com/ponylang/http_server",
"license": "BSD-2-Clause",
"documentation_url": "https://ponylang.github.io/http_server/",
"version": "0.4.6",
"version": "0.5.0",
"name": "http_server"
}
}
79 changes: 79 additions & 0 deletions http_server/_ignore_ascii_case.pony
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
primitive IgnoreAsciiCase
"""
Compares two strings lexicographically and case-insensitively.
Only works for ASCII strings.
"""

fun compare(left: String, right: String): Compare =>
"""
Less: left sorts lexicographically smaller than right
Equal: same size, same content
Greater: left sorts lexicographically higher than right
_compare("A", "B") ==> Less
_compare("AA", "A") ==> Greater
_compare("A", "AA") ==> Less
_compare("", "") ==> Equal
"""
let ls = left.size()
let rs = right.size()
let min = ls.min(rs)

var i = USize(0)
while i < min do
try
let lc = _lower(left(i)?)
let rc = _lower(right(i)?)
if lc < rc then
return Less
elseif rc < lc then
return Greater
end
else
Less // should not happen, size checked
end
i = i + 1
end
// all characters equal up to min size
if ls > min then
// left side is longer, so considered greater
Greater
elseif rs > min then
// right side is longer, so considered greater
Less
else
// both sides equal size and content
Equal
end

fun eq(left: String, right: String): Bool =>
"""
Returns true if both strings have the same size
and compare equal ignoring ASCII casing.
"""
if left.size() != right.size() then
false
else
var i: USize = 0
while i < left.size() do
try
if _lower(left(i)?) != _lower(right(i)?) then
return false
end
else
return false
end
i = i + 1
end
true
end

fun _lower(c: U8): U8 =>
if (c >= 0x41) and (c <= 0x5A) then
c + 0x20
else
c
end


2 changes: 1 addition & 1 deletion http_server/_pending_responses.pony
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type _PendingResponse is (RequestID, Vec[_ByteSeqs])

class ref _PendingResponses
// TODO: find out what is the most efficient way to
// keep and acucmulate a pending response
// keep and accumulate a pending response
// from ByteSeq and ByteSeqIter
embed _pending: Array[_PendingResponse] ref = _pending.create(0)

Expand Down
46 changes: 46 additions & 0 deletions http_server/_test_headers.pony
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use "collections"
use "debug"
use "pony_check"
use "pony_test"
Expand All @@ -9,6 +10,8 @@ actor \nodoc\ _HeaderTests is TestList

fun tag tests(test: PonyTest) =>
test(Property1UnitTest[Array[Header]](_HeadersGetProperty))
test(Property1UnitTest[Set[String]](_HeadersDeleteProperty))


class \nodoc\ iso _HeadersGetProperty is Property1[Array[Header]]
fun name(): String => "headers/get/property"
Expand Down Expand Up @@ -46,3 +49,46 @@ class \nodoc\ iso _HeadersGetProperty is Property1[Array[Header]]
end
end
end


class \nodoc\ iso _HeadersDeleteProperty is Property1[Set[String]]
fun name(): String => "headers/delete/property"

fun gen(): Generator[Set[String]] =>
// we need unique values in our set, lower and upper case letters are
// considered equal for our Headers impl, so we need to avoid e.g. `a` and
// `A` as the set thinks they are different, but Headers not.
Generators.set_of[String](Generators.ascii(where max=10, range=ASCIILettersLower))

fun property(sample: Set[String], h: PropertyHelper) =>
let headers = Headers.create()

let added: Array[String] = Array[String](sample.size())
let iter = sample.values()
try
let first = iter.next()?
for header in iter do
headers.add(header, header)
added.push(header)
end

h.log("Added headers:" where verbose = true)
for a in added.values() do
h.log(a where verbose = true)
end

// the header we never added is not inside
h.assert_true(headers.delete(first) is None, "Header: " + first + " got deleted from headers although never added")
for added_header in added.values() do

// available before delete
h.assert_true(headers.get(added_header) isnt None, "Header: " + added_header + " was added to headers, but wasn't retrieved with get")
h.assert_true(headers.delete(added_header) isnt None, "Header: " + added_header + " was added to headers, but wasn't found during delete")
// gone after delete
h.assert_true(headers.get(added_header) is None, "Header: " + added_header + " was deleted but could be retrieved with get")

// the header we never added is not inside
h.assert_true(headers.delete(first) is None, "Header: " + first + " got deleted from headers although never added")
end
end

18 changes: 0 additions & 18 deletions http_server/_test_reponse.pony

This file was deleted.

Loading

0 comments on commit d0d800e

Please sign in to comment.