Skip to content

Commit

Permalink
Merge branch '3.9.x' into 4.0.x
Browse files Browse the repository at this point in the history
  • Loading branch information
graemerocher committed Mar 11, 2023
2 parents 2f5c857 + af9c3fd commit 893bc15
Show file tree
Hide file tree
Showing 35 changed files with 805 additions and 54 deletions.
19 changes: 4 additions & 15 deletions .github/workflows/corretto.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: Corretto CI
on:
push:
branches:
- '[1-9]+.[0-9]+.x'
schedule:
- cron: "0 1 * * 1-5" # Mon-Fri at 1am UTC
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -39,20 +39,9 @@ jobs:
env:
GH_TOKEN_PUBLIC_REPOS_READONLY: ${{ secrets.GH_TOKEN_PUBLIC_REPOS_READONLY }}
GH_USERNAME: ${{ secrets.GH_USERNAME }}
MICRONAUT_TEST_USE_VENDOR: true
TESTCONTAINERS_RYUK_DISABLED: true
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }}
GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }}
PREDICTIVE_TEST_SELECTION: "${{ github.event_name == 'pull_request' && 'true' || 'false' }}"
- name: Add build scan URL as PR comment
uses: actions/github-script@v5
if: github.event_name == 'pull_request' && failure()
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '❌ ${{ github.workflow }} failed: ${{ steps.gradle.outputs.build-scan-url }}'
})
2 changes: 1 addition & 1 deletion .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
- name: Build with Gradle
id: gradle
run: |
./gradlew preReleaseCheck check --no-daemon --parallel --continue
./gradlew check --no-daemon --parallel --continue
env:
GH_TOKEN_PUBLIC_REPOS_READONLY: ${{ secrets.GH_TOKEN_PUBLIC_REPOS_READONLY }}
GH_USERNAME: ${{ secrets.GH_USERNAME }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Args = --features=io.micronaut.buffer.netty.NettyFeature
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public interface AnnotationScanner {
default @NonNull Stream<Class<?>> scan(@NonNull Class<? extends Annotation> annotation, @NonNull Collection<String> packages) {
Objects.requireNonNull(annotation, "Annotation type cannot be null");
Objects.requireNonNull(packages, "Packages to scan cannot be null");
return scan(annotation.getName(), packages.parallelStream());
return scan(annotation.getName(), packages.stream());
}

/**
Expand All @@ -134,7 +134,6 @@ public interface AnnotationScanner {
Objects.requireNonNull(packages, "Packages to scan cannot be null");

return packages
.parallel()
.flatMap(pkg -> scan(annotation, pkg));
}

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ kotlin.stdlib.default.dependency=false

# For the docs
graalVersion=22.0.0.2
micronautSecurityVersion=3.9.1
micronautSecurityVersion=3.9.3

org.gradle.caching=true
org.gradle.parallel=true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Args = --features=io.micronaut.http.netty.graal.HttpNettyFeature
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ public void noTokenization() {
/**
* Proceed until {@link #isBuffering()} becomes false.
*/
@SuppressWarnings("java:S3776")
private void proceedUntilNonBuffering(ByteBuf buf) throws JsonSyntaxException {
assert isBuffering();
int end = buf.writerIndex();
Expand Down Expand Up @@ -195,6 +196,7 @@ private void proceedUntilNonBuffering(ByteBuf buf) throws JsonSyntaxException {
* Consume some input until {@link #isBuffering()}. Sometimes this method returns before that
* is the case, to make the implementation simpler.
*/
@SuppressWarnings("java:S3776")
private void proceedUntilBuffering(ByteBuf buf) throws JsonSyntaxException {
assert !isBuffering();
assert depth == 0 : depth;
Expand Down Expand Up @@ -329,7 +331,7 @@ private void handleTopLevelScalarSpecial(byte b) throws JsonSyntaxException {
/**
* Handle a byte in the {@link State#ESCAPE} state.
*/
private void handleEscape(byte b) throws JsonSyntaxException {
private void handleEscape(byte b) {
state = State.STRING;
}

Expand Down Expand Up @@ -360,6 +362,7 @@ private void handleStringSpecial(byte b) throws JsonSyntaxException {
* @return {@code true} if this character does not change the state while in {@link State#BASE}
* and while not buffering
*/
@SuppressWarnings("java:S2178") // performance
private static boolean skipBufferingBase(byte b) {
return (b != '"') & (b != '{') & (b != '[') & (b != ']') & (b != '}');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ protected void setDateAndCacheHeaders(MutableHttpResponse response, long lastMod
// Date header
MutableHttpHeaders headers = response.getHeaders();
LocalDateTime now = LocalDateTime.now();
headers.date(now);
if (!headers.contains(HttpHeaders.DATE)) {
headers.date(now);
}

// Add cache headers
LocalDateTime cacheSeconds = now.plus(configuration.getCacheSeconds(), ChronoUnit.SECONDS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class FileTypeHandlerSpec extends AbstractMicronautSpec {
response.header(CONTENT_TYPE) == "text/html"
Integer.parseInt(response.header(CONTENT_LENGTH)) > 0
response.headers.getDate(DATE) < response.headers.getDate(EXPIRES)
response.headers.getAll(DATE).size() == 1
response.header(CACHE_CONTROL) == "private, max-age=60"
response.headers.getDate(LAST_MODIFIED) == ZonedDateTime.ofInstant(Instant.ofEpochMilli(tempFile.lastModified()), ZoneId.of("GMT")).truncatedTo(ChronoUnit.SECONDS)
response.body() == tempFileContents
Expand Down
6 changes: 3 additions & 3 deletions http-server-tck/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ dependencies {
}
annotationProcessor(projects.httpValidation)

compileOnly(platform(libs.test.boms.micronaut.validation))
compileOnly(libs.micronaut.validation) {
implementation(platform(libs.test.boms.micronaut.validation))
implementation(libs.micronaut.validation) {
exclude(group = "io.micronaut")
}
implementation(projects.runtime)
implementation(projects.jacksonDatabind)
implementation(projects.inject)

implementation(projects.management)
api(projects.httpTck)
api(projects.httpServer)
api(projects.httpClientCore)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2017-2023 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.http.server.tck.tests;

import io.micronaut.context.annotation.Requires;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Header;
import io.micronaut.http.server.tck.AssertionUtils;
import io.micronaut.http.server.tck.HttpResponseAssertion;
import org.junit.jupiter.api.Test;

import java.io.IOException;

import static io.micronaut.http.server.tck.TestScenario.asserts;

@SuppressWarnings({
"java:S5960", // We're allowed assertions, as these are used in tests only
"checkstyle:MissingJavadocType",
"checkstyle:DesignForExtension"
})
public class HeadersTest {
public static final String SPEC_NAME = "HeadersTest";

/**
* Message header field names are case-insensitive
*
* @see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2">HTTP/1.1 Message Headers</a>
*/
@Test
void headersAreCaseInsensitiveAsPerMessageHeadersSpecification() throws IOException {
// standard header name with mixed case
asserts(SPEC_NAME,
HttpRequest.GET("/foo/ok").header("aCcEpT", MediaType.APPLICATION_JSON),
(server, request) -> AssertionUtils.assertDoesNotThrow(server, request, HttpResponseAssertion.builder()
.status(HttpStatus.OK)
.body("{\"status\":\"ok\"}")
.build()));
// custom header name with mixed case
asserts(SPEC_NAME,
HttpRequest.GET("/foo/bar").header("fOO", "ok"),
(server, request) -> AssertionUtils.assertDoesNotThrow(server, request, HttpResponseAssertion.builder()
.status(HttpStatus.OK)
.body("{\"status\":\"ok\"}")
.build()));
}

@Controller("/foo")
@Requires(property = "spec.name", value = SPEC_NAME)
static class ProduceController {
@Get(value = "/ok", produces = MediaType.APPLICATION_JSON)
String getOkAsJson() {
return "{\"status\":\"ok\"}";
}

@Get(value = "/bar", produces = MediaType.APPLICATION_JSON)
String getFooAsJson(@Header("Foo") String foo) {
return "{\"status\":\"" + foo + "\"}";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2017-2023 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.http.server.tck.tests.endpoints.health;

import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.server.tck.AssertionUtils;
import io.micronaut.http.server.tck.HttpResponseAssertion;
import org.junit.jupiter.api.Test;

import java.io.IOException;

import static io.micronaut.http.server.tck.TestScenario.asserts;

@SuppressWarnings({
"java:S5960", // We're allowed assertions, as these are used in tests only
"checkstyle:MissingJavadocType",
"checkstyle:DesignForExtension"
})
public class HealthTest {
private static final String SPEC_NAME = "HealthTest";

/**
* This test verifies health endpoint is exposed. The server under test needs to publish the {@link io.micronaut.discovery.event.ServiceReadyEvent} or {@link io.micronaut.runtime.server.event.ServerStartupEvent} for {@link io.micronaut.management.health.indicator.service.ServiceReadyHealthIndicator} to be UP.
* @throws IOException Exception thrown while getting the server under test.
*/
@Test
public void healthEndpointExposed() throws IOException {
// standard header name with mixed case
asserts(SPEC_NAME,
HttpRequest.GET("/health"),
(server, request) -> AssertionUtils.assertDoesNotThrow(server, request, HttpResponseAssertion.builder()
.status(HttpStatus.OK)
.body("{\"status\":\"UP\"}")
.build()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class HttpServerFilterExceptionHandlerTest {
@Test
public void exceptionHandlerTest() throws IOException {
assertion(HttpRequest.GET("/foo"),
AssertionUtils.assertThrowsStatus(HttpStatus.UNPROCESSABLE_ENTITY));
AssertionUtils.assertThrowsStatus(HttpStatus.UNPROCESSABLE_ENTITY));
}

private static void assertion(HttpRequest<?> request, BiConsumer<ServerUnderTest, HttpRequest<?>> assertion) throws IOException {
Expand Down
Loading

0 comments on commit 893bc15

Please sign in to comment.