@@ -10,6 +10,172 @@ The format is based on [Keep a Changelog][], and this project adheres to [Semant
10
10
[ Keep a Changelog ] : https://keepachangelog.com/en/1.1.0/
11
11
[ Semantic Versioning ] : https://semver.org/spec/v2.0.0.html
12
12
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
+
13
179
## [ v0.99.79] - 2025-03-31
14
180
15
181
### Added
@@ -4935,6 +5101,7 @@ This is the final release of `lkrms/util`. It is moving to [Salient](https://git
4935
5101
4936
5102
- Allow `CliOption` value names to contain arbitrary characters
4937
5103
5104
+ [v0.99.80]: https://github.com/salient-labs/toolkit/compare/v0.99.79...v0.99.80
4938
5105
[v0.99.79]: https://github.com/salient-labs/toolkit/compare/v0.99.78...v0.99.79
4939
5106
[v0.99.78]: https://github.com/salient-labs/toolkit/compare/v0.99.77...v0.99.78
4940
5107
[v0.99.77]: https://github.com/salient-labs/toolkit/compare/v0.99.76...v0.99.77
0 commit comments