Skip to content

Commit

Permalink
Merge pull request #2178 from ballerina-platform/fix-add-header
Browse files Browse the repository at this point in the history
Fix `Content-Type` header duplication via `addHeader` method
  • Loading branch information
TharmiganK authored Oct 16, 2024
2 parents 437770e + 7905e2e commit f648d03
Show file tree
Hide file tree
Showing 16 changed files with 52 additions and 15 deletions.
2 changes: 1 addition & 1 deletion ballerina-tests/http-advanced-tests/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "io"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina-tests/http-client-tests/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "io"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina-tests/http-dispatching-tests/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "io"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina-tests/http-interceptor-tests/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "io"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina-tests/http-misc-tests/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "io"},
Expand Down
22 changes: 22 additions & 0 deletions ballerina-tests/http-misc-tests/tests/http_header_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// specific language governing permissions and limitations
// under the License.

import ballerina/mime;
import ballerina/test;
import ballerina/http;
import ballerina/http_test_common as common;
Expand Down Expand Up @@ -276,6 +277,27 @@ function testPassthruWithBody() returns error? {
}
}

@test:Config {}
function testAddHeaderWithContentType() returns error? {
http:Request req = new;
check req.setContentType(mime:APPLICATION_JSON);
test:assertEquals(check req.getHeaders(http:CONTENT_TYPE), [mime:APPLICATION_JSON]);
req.addHeader(http:CONTENT_TYPE, mime:APPLICATION_XML);
test:assertEquals(check req.getHeaders(http:CONTENT_TYPE), [mime:APPLICATION_XML]);

http:Response res = new;
check res.setContentType(mime:APPLICATION_JSON);
test:assertEquals(check res.getHeaders(http:CONTENT_TYPE), [mime:APPLICATION_JSON]);
res.addHeader(http:CONTENT_TYPE, mime:APPLICATION_XML);
test:assertEquals(check res.getHeaders(http:CONTENT_TYPE), [mime:APPLICATION_XML]);

http:PushPromise pushPromise = new;
pushPromise.addHeader(http:CONTENT_TYPE, mime:APPLICATION_JSON);
test:assertEquals(pushPromise.getHeaders(http:CONTENT_TYPE), [mime:APPLICATION_JSON]);
pushPromise.addHeader(http:CONTENT_TYPE, mime:APPLICATION_XML);
test:assertEquals(pushPromise.getHeaders(http:CONTENT_TYPE), [mime:APPLICATION_XML]);
}

type Headers record {|
@http:Header {name: "X-API-VERSION"}
string apiVersion;
Expand Down
2 changes: 1 addition & 1 deletion ballerina-tests/http-resiliency-tests/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "io"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina-tests/http-security-tests/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "io"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina-tests/http-service-tests/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "io"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina-tests/http-test-common/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ modules = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
dependencies = [
{org = "ballerina", name = "io"},
{org = "ballerina", name = "jballerina.java"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina-tests/http2-tests/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "io"},
Expand Down
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ modules = [
[[package]]
org = "ballerina"
name = "mime"
version = "2.10.0"
version = "2.10.1"
dependencies = [
{org = "ballerina", name = "io"},
{org = "ballerina", name = "jballerina.java"},
Expand Down
6 changes: 5 additions & 1 deletion ballerina/http2_push_promise.bal
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ public class PushPromise {
return externPromiseGetHeaders(self, headerName);
}

# Adds the specified key/value pair as an HTTP header to the `http:PushPromise`.
# Adds the specified key/value pair as an HTTP header to the `http:PushPromise`. In the case of the `Content-Type`
# header, the existing value is replaced with the specified value.
#
# + headerName - The header name
# + headerValue - The header value
public isolated function addHeader(string headerName, string headerValue) {
if headerName.equalsIgnoreCaseAscii(CONTENT_TYPE) {
return externPromiseSetHeader(self, headerName, headerValue);
}
return externPromiseAddHeader(self, headerName, headerValue);
}

Expand Down
9 changes: 7 additions & 2 deletions ballerina/http_request.bal
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,17 @@ public class Request {
externRequestSetHeader(self, headerName, headerValue);
}

# Adds the specified header to the request. Existing header values are not replaced. Panic if an illegal header is passed.
# Adds the specified header to the request. Existing header values are not replaced, except for the `Content-Type`
# header. In the case of the `Content-Type` header, the existing value is replaced with the specified value.
# Panic if an illegal header is passed.
#
# + headerName - The header name
# + headerValue - The header value
public isolated function addHeader(string headerName, string headerValue) {
externRequestAddHeader(self, headerName, headerValue);
if headerName.equalsIgnoreCaseAscii(CONTENT_TYPE) {
return externRequestSetHeader(self, headerName, headerValue);
}
return externRequestAddHeader(self, headerName, headerValue);
}

# Removes the specified header from the request.
Expand Down
7 changes: 6 additions & 1 deletion ballerina/http_response.bal
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,18 @@ public class Response {
return externResponseGetHeader(self, headerName, position);
}

# Adds the specified header to the response. Existing header values are not replaced. Panic if an illegal header is passed.
# Adds the specified header to the response. Existing header values are not replaced, except for the `Content-Type`
# header. In the case of the `Content-Type` header, the existing value is replaced with the specified value.
#. Panic if an illegal header is passed.
#
# + headerName - The header name
# + headerValue - The header value
# + position - Represents the position of the header as an optional parameter. If the position is `http:TRAILING`,
# the entity-body of the `Response` must be accessed initially.
public isolated function addHeader(string headerName, string headerValue, HeaderPosition position = LEADING) {
if headerName.equalsIgnoreCaseAscii(CONTENT_TYPE) {
return externResponseSetHeader(self, headerName, headerValue, position);
}
return externResponseAddHeader(self, headerName, headerValue, position);
}

Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Fixed

- [Address CVE-2024-7254 vulnerability](https://github.com/ballerina-platform/ballerina-library/issues/7013)
- [Fix duplicating `Content-Type` header via the `addHeader` method](https://github.com/ballerina-platform/ballerina-library/issues/7268)

## [2.12.0] - 2024-08-20

Expand Down

0 comments on commit f648d03

Please sign in to comment.