Skip to content

Commit 9042a5f

Browse files
committed
Release v0.99.80
1 parent 6700a05 commit 9042a5f

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

CHANGELOG.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,172 @@ The format is based on [Keep a Changelog][], and this project adheres to [Semant
1010
[Keep a Changelog]: https://keepachangelog.com/en/1.1.0/
1111
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
1212

13+
## [v0.99.80] - 2025-09-05
14+
15+
- Review referenced RFCs for compliance, clarity and currency
16+
- Rename `Regex::UUID` to `UUID_V4`
17+
- Add `Regex::UUID` to match all UUIDs and adopt in `AbstractSyncProvider::isValidIdentifier()`
18+
- Normalise exception variable names as `$ex`
19+
20+
### Added
21+
22+
#### `Cli`
23+
24+
- Add `CliUtil` with `getJson()` and consolidate similar methods
25+
26+
#### `Collection`
27+
28+
- Add dictionary interface, class and trait
29+
30+
#### `Http`
31+
32+
- Add `getHeaderLines()` alongside existing `getHeaderLine()` methods
33+
- Add `HeadersInterface` methods `hasBadWhitespace()` and `hasObsoleteLineFolding()`
34+
- Add `MultipartStreamInterface::getParts()` for completeness
35+
36+
### Changed
37+
38+
#### `Collection`
39+
40+
- Allow `Arrayable::toArray()` return type variations by adding an optional `TArrayValue` template to `DictionaryInterface` and `CollectionInterface`
41+
- Move `toArray()` from `ReadOnlyCollectionTrait` to `RecursiveArrayableCollectionTrait`
42+
- Add non-recursive implementation of `toArray()` to `ArrayableCollectionTrait`
43+
44+
#### `Curler`
45+
46+
- Pass the number of entities returned from the endpoint via previous pages to `CurlerPagerInterface::getPage()`
47+
- Rename `METHOD_HAS_BODY` to `REQUEST_METHOD_HAS_BODY` (to prevent conflict with other `METHOD_*` constants)
48+
- Rename methods for consistency with `Http` changes:
49+
- `getPublicHttpHeaders()` -> `getPublicHeaders()`
50+
- `hasAccessToken()` -> `hasCredential()`
51+
- `withAccessToken()` -> `withCredential()`
52+
53+
#### `Http`
54+
55+
<details>
56+
<summary>Move and rename various interfaces, classes, traits and members</summary>
57+
58+
- Rename:
59+
- `AccessTokenInterface` -> `CredentialInterface`
60+
- `getTokenType()` -> `getAuthenticationScheme()`
61+
- `getToken()` -> `getCredential()`
62+
- `HttpHeadersInterface` -> `HeadersInterface`
63+
- `hasLastLine()` -> `hasEmptyLine()`
64+
- `append()` -> `addValue()`
65+
- `canonicalize()` -> `normalise()`
66+
- `HasHttpHeaders` (interface) -> `HasInnerHeaders`
67+
- `getHttpHeaders()` -> `getInnerHeaders()`
68+
- `HttpHeaders` -> `Headers`
69+
- `HasHttpHeaders` (trait) -> `HasInnerHeadersTrait`
70+
- `HttpServer` -> `Server` and move to separate namespace
71+
- `Stream::copyToString()` -> `getStreamContents()` and move to `HttpUtil`
72+
- `Stream::copyToStream()` -> `copyStream()` and move to `HttpUtil`
73+
- `UriInterface::toParts()` -> `getComponents()`
74+
- `UriInterface::isReference()` -> `isRelativeReference()`
75+
- `Uri::EXPAND_EMPTY_PATH` -> `NORMALISE_EMPTY_PATH`
76+
- `Uri::COLLAPSE_MULTIPLE_SLASHES` -> `NORMALISE_MULTIPLE_SLASHES`
77+
- `HttpUtil::escapeQuotedString()` -> `quoteString()`
78+
- `HttpUtil::getNameValueGenerator()` -> `getNameValuePairs()`
79+
- `HttpServerException` -> `ServerException`
80+
- `StreamDetachedException` -> `StreamClosedException`
81+
- `StreamInvalidRequestException` -> `InvalidStreamRequestException`
82+
- `UploadedFileException` -> `UploadFailedException`
83+
- Move:
84+
- `Headers::getContentLength()` to `HttpUtil`
85+
- `Headers::getMultipartBoundary()` to `HttpUtil`
86+
- `Headers::getPreferences()` to `HttpUtil`
87+
- `Headers::mergePreferences()` to `HttpUtil`
88+
- `Headers::getRetryAfter()` to `HttpUtil`
89+
- `Uri::isAuthorityForm()` to `HttpUtil`
90+
- Move message-related interfaces to their own namespace and rename:
91+
- `HttpMessageInterface` -> `MessageInterface`
92+
- `HttpMultipartStreamInterface` -> `MultipartStreamInterface`
93+
- `HttpRequestInterface` -> `RequestInterface`
94+
- `HttpResponseInterface` -> `ResponseInterface`
95+
- `HttpServerRequestInterface` -> `ServerRequestInterface`
96+
- `HttpStreamInterface` -> `StreamInterface`
97+
- `HttpMultipartStreamPartInterface` -> `StreamPartInterface`
98+
- `getFallbackFilename()` -> `getAsciiFilename()`
99+
- `getContent()` -> `getBody()`
100+
- Move message-related classes to their own namespace and rename:
101+
- `AbstractHttpMessage` -> `AbstractMessage`
102+
- `AbstractHttpRequest` -> `AbstractRequest`
103+
- `HttpFactory` -> `MessageFactory`
104+
- `HttpMultipartStream` -> `MultipartStream`
105+
- `HttpRequest` -> `Request`
106+
- `HttpResponse` -> `Response`
107+
- `HttpServerRequest` -> `ServerRequest`
108+
- `HttpServerRequestUpload` -> `ServerRequestUpload`
109+
- `HttpStream` -> `Stream`
110+
- `HttpMultipartStreamPart` -> `StreamPart`
111+
- Rename `FormDataFlag` to `HasFormDataFlag`, add `DATA_` prefix to the names of its constants and access them via implementations
112+
- Rename `MimeType` to `HasMediaType`, add `TYPE_` prefix to the names of its constants and access them via implementations
113+
- Rename `HttpRequestMethod` to `HasRequestMethod`, add `METHOD_` prefix to the names of its constants and access them via implementations
114+
- Rename `HttpHeader` to `HasHttpHeader`, add `HEADER_` prefix to the names of its constants and access them via implementations
115+
- Rename `HttpHeaderGroup` to `HasHttpHeaders`, add `HEADERS_` prefix to the names of its constants and access them via implementations
116+
</details>
117+
118+
- In `HeadersInterface`, extend `DictionaryInterface` (new) instead of `CollectionInterface`
119+
- In `Headers::addLine()`:
120+
- Throw an exception on invalid header field syntax or line folding even if `$strict` is `false`
121+
- Throw `LogicException` if called after headers are applied via another method
122+
- Throw `InvalidHeaderException` instead of `InvalidArgumentException`
123+
- In `Headers::map()`, return the same instance if mapped values are equivalent
124+
- In `HttpUtil::quoteString()`, add double quotes
125+
- In `UriInterface`, remove nullability from `parse()` parameter `$component`
126+
- In `Uri::parse()`, replicate `parse_url()` behaviour when URI and component are both invalid (i.e. return `false`)
127+
- In `AbstractMessage`/`AbstractRequest`:
128+
- Don't apply an implicit media type to messages with multipart bodies
129+
- Normalise headers when casting messages to strings
130+
- In `MultipartStream`, do not remain operational after `close()` or `detach()` are called
131+
- Refactor `Server` for compliance and consistency
132+
- Rename:
133+
- `getProxyTls()` -> `proxyHasTls()`
134+
- `getProxyBasePath()` -> `getProxyPath()`
135+
- `getBaseUri()` -> `getUri()` and return `Uri`, not `string`
136+
- Add:
137+
- `getLocalIpAddress()`
138+
- `getLocalPort()` to improve support for dynamic port allocation
139+
- Allow `stop()` to be called when the server is not running
140+
- In `listen()`:
141+
- Replace `$callback` with `$listener`, which returns a `ServerResponse` instead of receiving control variables by reference
142+
- Keep listening for requests until a response has a return value unless a non-negative `$limit` is given
143+
- Add request target validity checks
144+
- Respond to invalid requests with "400 Bad Request" or "501 Not Implemented" and don't throw the underlying exception by default
145+
- Throw `LogicException` when:
146+
- `getProxy*()` is called on an instance with no proxy, or
147+
- an assertion fails (instead of `ServerException`)
148+
- Adopt terminology and behaviour of \[RFC9112], \[RFC9110] and \[RFC8187], which supercede \[RFC7230], \[RFC7231] and \[RFC5987]
149+
- Replace "header line" with "field line" where appropriate
150+
- In `Headers::addLine()`, don't throw `InvalidHeaderException` when bad whitespace is received and `$strict = true`
151+
- Use `getLastHeaderValue()` when retrieving `Content-Type` headers
152+
- Use `getOnlyHeaderValue()` when retrieving `Location` headers
153+
154+
### Removed
155+
156+
#### `Http`
157+
158+
- Remove superfluous `MessageInterface::getHttpPayload()`
159+
- Remove `$strict` parameter from `HeadersInterface::addLine()` (implementation detail)
160+
- Remove unused `Uri` methods:
161+
- `fromParts()`
162+
- `unparse()`
163+
- `resolveReference()`
164+
- `removeDotSegments()`
165+
- Remove superfluous `Server::getScheme()`
166+
- Remove unused `HttpRequestHandlerInterface`
167+
168+
### Fixed
169+
170+
#### `Http`
171+
172+
- Fix issue where message objects cast to strings may have too many empty lines between headers and body
173+
- Fix `AbstractRequest` issue where request target type `origin-form` may be incorrectly detected when the given URI has an empty path
174+
- Fix `Headers::addLine()` issue where invalid line folding in the first trailer may not be detected
175+
- Fix `Headers::getHeaderLine()` issue where headers with unquoted commas may be inadvertently modified
176+
- Fix `HttpUtil::getRetryAfter()` issue where negative delay seconds are parsed as a timestamp
177+
- Fix `Server` issue where large responses might not be written in full
178+
13179
## [v0.99.79] - 2025-03-31
14180

15181
### Added
@@ -4935,6 +5101,7 @@ This is the final release of `lkrms/util`. It is moving to [Salient](https://git
49355101

49365102
- Allow `CliOption` value names to contain arbitrary characters
49375103

5104+
[v0.99.80]: https://github.com/salient-labs/toolkit/compare/v0.99.79...v0.99.80
49385105
[v0.99.79]: https://github.com/salient-labs/toolkit/compare/v0.99.78...v0.99.79
49395106
[v0.99.78]: https://github.com/salient-labs/toolkit/compare/v0.99.77...v0.99.78
49405107
[v0.99.77]: https://github.com/salient-labs/toolkit/compare/v0.99.76...v0.99.77

0 commit comments

Comments
 (0)