Skip to content

Commit b5a7662

Browse files
authored
Ignore appending allow origin if already present (#1371)
1 parent 42dabd6 commit b5a7662

File tree

15 files changed

+589
-30
lines changed

15 files changed

+589
-30
lines changed

runtime/binding-http/src/main/java/io/aklivity/zilla/runtime/binding/http/internal/stream/HttpServerFactory.java

+43-30
Original file line numberDiff line numberDiff line change
@@ -2415,46 +2415,55 @@ private void doEncodeHeaders(
24152415
final String origin = exchange.origin;
24162416
final HttpPolicyConfig policy = exchange.policy;
24172417
final HttpAccessControlConfig access = binding.access();
2418-
HttpHeaderFW allowOrigin = access.allowOriginHeader(policy, origin);
2419-
if (allowOrigin != null)
2420-
{
2421-
codecOffset.value = doEncodeHeader(codecBuffer, codecOffset.value, allowOrigin);
2422-
}
24232418

2424-
HttpHeaderFW allowCredentials = access.allowCredentialsHeader();
2425-
if (allowCredentials != null)
2426-
{
2427-
codecOffset.value = doEncodeHeader(codecBuffer, codecOffset.value, allowCredentials);
2428-
}
2419+
final HttpHeaderFW allowCrossOrigin = headers.matchFirst(h ->
2420+
HEADER_ACCESS_CONTROL_ALLOW_ORIGIN.equals(h.name()));
24292421

2430-
if (access.exposeHeadersExplicit())
2422+
if (allowCrossOrigin == null)
24312423
{
2432-
headers.forEach(h ->
2424+
HttpHeaderFW allowOrigin = access.allowOriginHeader(policy, origin);
2425+
2426+
if (allowOrigin != null)
24332427
{
2434-
final String8FW name = h.name();
2435-
if (access.exposeHeader(name.asString()))
2428+
codecOffset.value = doEncodeHeader(codecBuffer, codecOffset.value, allowOrigin);
2429+
}
2430+
2431+
HttpHeaderFW allowCredentials = access.allowCredentialsHeader();
2432+
if (allowCredentials != null)
2433+
{
2434+
codecOffset.value = doEncodeHeader(codecBuffer, codecOffset.value, allowCredentials);
2435+
}
2436+
2437+
if (access.exposeHeadersExplicit())
2438+
{
2439+
headers.forEach(h ->
24362440
{
2437-
String8FW expose = HEADER_ACCESS_CONTROL_EXPOSE_HEADERS;
2438-
codecOffset.value = doEncodeHeader(codecBuffer, codecOffset.value, expose.value(), name.value(), true);
2441+
final String8FW name = h.name();
2442+
if (access.exposeHeader(name.asString()))
2443+
{
2444+
String8FW expose = HEADER_ACCESS_CONTROL_EXPOSE_HEADERS;
2445+
codecOffset.value = doEncodeHeader(codecBuffer, codecOffset.value,
2446+
expose.value(), name.value(), true);
2447+
}
2448+
});
2449+
}
2450+
else if (access.exposeHeaders())
2451+
{
2452+
if (headers.anyMatch(h -> access.exposeHeader(h.name().asString())))
2453+
{
2454+
codecOffset.value = doEncodeHeader(codecBuffer, codecOffset.value,
2455+
HEADER_ACCESS_CONTROL_EXPOSE_HEADERS_WILDCARD);
24392456
}
2440-
});
2441-
}
2442-
else if (access.exposeHeaders())
2443-
{
2444-
if (headers.anyMatch(h -> access.exposeHeader(h.name().asString())))
2457+
}
2458+
2459+
if (allowOrigin != null &&
2460+
!allowOrigin.equals(HEADER_ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD))
24452461
{
24462462
codecOffset.value = doEncodeHeader(codecBuffer, codecOffset.value,
2447-
HEADER_ACCESS_CONTROL_EXPOSE_HEADERS_WILDCARD);
2463+
HEADER_VARY_ORIGIN, true);
24482464
}
24492465
}
24502466

2451-
if (allowOrigin != null &&
2452-
!allowOrigin.equals(HEADER_ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD))
2453-
{
2454-
codecOffset.value = doEncodeHeader(codecBuffer, codecOffset.value,
2455-
HEADER_VARY_ORIGIN, true);
2456-
}
2457-
24582467
codecBuffer.putBytes(codecOffset.value, CRLF_BYTES);
24592468
codecOffset.value += CRLF_BYTES.length;
24602469

@@ -6844,9 +6853,13 @@ void encodeHeaders(
68446853
headerBlock.header(b -> b.literal(l -> l.type(WITHOUT_INDEXING).name(54).value(server.value())));
68456854
}
68466855

6847-
if (access != null)
6856+
final HttpHeaderFW allowCrossOrigin = headers.matchFirst(h ->
6857+
HEADER_ACCESS_CONTROL_ALLOW_ORIGIN.equals(h.name()));
6858+
6859+
if (allowCrossOrigin == null && access != null)
68486860
{
68496861
HttpHeaderFW allowOrigin = access.allowOriginHeader(policy, origin);
6862+
68506863
if (allowOrigin != null)
68516864
{
68526865
headerBlock.header(b -> encodeHeader(allowOrigin, b));

runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7230/server/AccessControlIT.java

+22
Original file line numberDiff line numberDiff line change
@@ -340,4 +340,26 @@ public void shouldAllowCredentialsCookie() throws Exception
340340
{
341341
k3po.finish();
342342
}
343+
344+
@Test
345+
@Configuration("server.access.control.cross.origin.allow.explicit.yaml")
346+
@Specification({
347+
"${net}/allow.origin.present/client",
348+
"${app}/allow.origin.present/server",
349+
})
350+
public void shouldNotDefaultExplicitAllowOriginWhenPresent() throws Exception
351+
{
352+
k3po.finish();
353+
}
354+
355+
@Test
356+
@Configuration("server.access.control.cross.origin.yaml")
357+
@Specification({
358+
"${net}/allow.origin.present/client",
359+
"${app}/allow.origin.present/server",
360+
})
361+
public void shouldNotDefaultImplicitAllowOriginWhenPresent() throws Exception
362+
{
363+
k3po.finish();
364+
}
343365
}

runtime/binding-http/src/test/java/io/aklivity/zilla/runtime/binding/http/internal/streams/rfc7540/server/AccessControlIT.java

+22
Original file line numberDiff line numberDiff line change
@@ -364,4 +364,26 @@ public void shouldAllowCredentialsCookie() throws Exception
364364
{
365365
k3po.finish();
366366
}
367+
368+
@Test
369+
@Configuration("server.access.control.cross.origin.allow.explicit.yaml")
370+
@Specification({
371+
"${net}/allow.origin.present/client",
372+
"${app}/allow.origin.present/server",
373+
})
374+
public void shouldNotDefaultExplicitAllowOriginWhenPresent() throws Exception
375+
{
376+
k3po.finish();
377+
}
378+
379+
@Test
380+
@Configuration("server.access.control.cross.origin.yaml")
381+
@Specification({
382+
"${net}/allow.origin.present/client",
383+
"${app}/allow.origin.present/server",
384+
})
385+
public void shouldNotDefaultImplicitAllowOriginWhenPresent() throws Exception
386+
{
387+
k3po.finish();
388+
}
367389
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#
2+
# Copyright 2021-2024 Aklivity Inc.
3+
#
4+
# Aklivity licenses this file to you under the Apache License,
5+
# version 2.0 (the "License"); you may not use this file except in compliance
6+
# with the License. You may obtain a copy of the License at:
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
#
16+
17+
connect "zilla://streams/app0"
18+
option zilla:window 40000
19+
option zilla:transmission "half-duplex"
20+
21+
22+
write zilla:begin.ext ${http:beginEx()
23+
.typeId(zilla:id("http"))
24+
.header(":method", "GET")
25+
.header(":scheme", "https")
26+
.header(":path", "/")
27+
.header(":authority", "example.com:9090")
28+
.header("origin", "https://example.net:9090")
29+
.build()}
30+
31+
connected
32+
33+
write flush
34+
35+
write close
36+
37+
read zilla:begin.ext ${http:matchBeginEx()
38+
.typeId(zilla:id("http"))
39+
.header(":status", "200")
40+
.header("server", "Zilla")
41+
.header("date", "Tue, 02 Feb 2022 22:22:22 GMT")
42+
.header("content-type", "text/plain; charset=UTF-8")
43+
.header("content-length", "12")
44+
.header("access-control-allow-origin", "https://example.net:9090")
45+
.build()}
46+
47+
read "Hello, world"
48+
49+
read closed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#
2+
# Copyright 2021-2024 Aklivity Inc.
3+
#
4+
# Aklivity licenses this file to you under the Apache License,
5+
# version 2.0 (the "License"); you may not use this file except in compliance
6+
# with the License. You may obtain a copy of the License at:
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
#
16+
17+
accept "zilla://streams/app0"
18+
option zilla:window 40000
19+
option zilla:transmission "half-duplex"
20+
accepted
21+
22+
read zilla:begin.ext ${http:matchBeginEx()
23+
.typeId(zilla:id("http"))
24+
.header(":method", "GET")
25+
.header(":scheme", "https")
26+
.header(":path", "/")
27+
.header(":authority", "example.com:9090")
28+
.header("origin", "https://example.net:9090")
29+
.build()}
30+
connected
31+
32+
read closed
33+
34+
write zilla:begin.ext ${http:beginEx()
35+
.typeId(zilla:id("http"))
36+
.header(":status", "200")
37+
.header("server", "Zilla")
38+
.header("date", "Tue, 02 Feb 2022 22:22:22 GMT")
39+
.header("content-type", "text/plain; charset=UTF-8")
40+
.header("content-length", "12")
41+
.header("access-control-allow-origin", "https://example.net:9090")
42+
.build()}
43+
44+
write "Hello, world"
45+
write flush
46+
47+
write close
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#
2+
# Copyright 2021-2024 Aklivity Inc.
3+
#
4+
# Aklivity licenses this file to you under the Apache License,
5+
# version 2.0 (the "License"); you may not use this file except in compliance
6+
# with the License. You may obtain a copy of the License at:
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
#
16+
17+
connect "zilla://streams/app0"
18+
option zilla:window 40000
19+
option zilla:transmission "half-duplex"
20+
21+
22+
write zilla:begin.ext ${http:beginEx()
23+
.typeId(zilla:id("http"))
24+
.header(":method", "GET")
25+
.header(":scheme", "https")
26+
.header(":path", "/")
27+
.header(":authority", "example.com:9090")
28+
.header("origin", "https://example.net:9090")
29+
.build()}
30+
31+
connected
32+
33+
write flush
34+
35+
write close
36+
37+
read zilla:begin.ext ${http:matchBeginEx()
38+
.typeId(zilla:id("http"))
39+
.header(":status", "200")
40+
.header("server", "Zilla")
41+
.header("date", "Tue, 02 Feb 2022 22:22:22 GMT")
42+
.header("content-type", "text/plain; charset=UTF-8")
43+
.header("content-length", "12")
44+
.header("access-control-allow-origin", "https://example.net:9090")
45+
.build()}
46+
47+
read "Hello, world"
48+
49+
read closed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#
2+
# Copyright 2021-2024 Aklivity Inc.
3+
#
4+
# Aklivity licenses this file to you under the Apache License,
5+
# version 2.0 (the "License"); you may not use this file except in compliance
6+
# with the License. You may obtain a copy of the License at:
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
#
16+
17+
accept "zilla://streams/app0"
18+
option zilla:window 40000
19+
option zilla:transmission "half-duplex"
20+
accepted
21+
22+
read zilla:begin.ext ${http:matchBeginEx()
23+
.typeId(zilla:id("http"))
24+
.header(":method", "GET")
25+
.header(":scheme", "https")
26+
.header(":path", "/")
27+
.header(":authority", "example.com:9090")
28+
.header("origin", "https://example.net:9090")
29+
.build()}
30+
connected
31+
32+
read closed
33+
34+
write zilla:begin.ext ${http:beginEx()
35+
.typeId(zilla:id("http"))
36+
.header(":status", "200")
37+
.header("server", "Zilla")
38+
.header("date", "Tue, 02 Feb 2022 22:22:22 GMT")
39+
.header("content-type", "text/plain; charset=UTF-8")
40+
.header("content-length", "12")
41+
.header("access-control-allow-origin", "https://example.net:9090")
42+
.build()}
43+
44+
write "Hello, world"
45+
write flush
46+
47+
write close

0 commit comments

Comments
 (0)