mirror of
https://gitee.com/dcren/initializr.git
synced 2025-09-19 10:08:22 +08:00
Redirect browsers to https when forceSsl is set
This commit extends the forceSsl support to redirect any HTML content to https. Practically speaking, this allows to redirect all browsers to https when they land on the main page using https. Serving traffic via http is still allowed as preventing this would break a lot of existing clients. To allow to easily run the app locally, forceSsl is false and must be enabled for any production environment. Closes gh-473
This commit is contained in:
@@ -33,8 +33,9 @@ download the Spring Boot CLI distribution bundle. This is only used by the `/spr
|
|||||||
endpoint at the moment.
|
endpoint at the moment.
|
||||||
* `springBootMetadataUrl` the URL of the resource that provides the list of available
|
* `springBootMetadataUrl` the URL of the resource that provides the list of available
|
||||||
Spring Boot versions..
|
Spring Boot versions..
|
||||||
* `forceSsl`: a boolean flag that determines if we should use `https` even when
|
* `forceSsl`: a boolean flag that determines if we should redirect browser to `https` when
|
||||||
browsing a resource via `http`. This is _enabled_ by default.
|
browsing via `http`. Also force the use of `https` in all links. This is not enabled by
|
||||||
|
default to ease local use case but should be enabled in production.
|
||||||
* `fallbackApplicationName`: the name of the _default_ application. Application names
|
* `fallbackApplicationName`: the name of the _default_ application. Application names
|
||||||
are generated based on the project's name. However, some user input may result in an
|
are generated based on the project's name. However, some user input may result in an
|
||||||
invalid identifier for a Java class name for instance.
|
invalid identifier for a Java class name for instance.
|
||||||
|
@@ -197,9 +197,10 @@ public class InitializrConfiguration {
|
|||||||
Collections.singletonList("org.springframework"));
|
Collections.singletonList("org.springframework"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force SSL support. When enabled, any access using http generate https links.
|
* Force SSL support. When enabled, any access using http generate https links and
|
||||||
|
* browsers are redirected to https for html content.
|
||||||
*/
|
*/
|
||||||
private boolean forceSsl = true;
|
private boolean forceSsl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "BillOfMaterials" that are referenced in this instance, identified by an
|
* The "BillOfMaterials" that are referenced in this instance, identified by an
|
||||||
|
@@ -81,7 +81,7 @@ public class InitializrMetadataBuilderTests {
|
|||||||
.withInitializrMetadata(
|
.withInitializrMetadata(
|
||||||
new ClassPathResource("metadata/config/test-min.json"))
|
new ClassPathResource("metadata/config/test-min.json"))
|
||||||
.build();
|
.build();
|
||||||
assertThat(metadata.getConfiguration().getEnv().isForceSsl()).isEqualTo(false);
|
assertThat(metadata.getConfiguration().getEnv().isForceSsl()).isEqualTo(true);
|
||||||
assertThat(metadata.getDependencies().getContent()).hasSize(1);
|
assertThat(metadata.getDependencies().getContent()).hasSize(1);
|
||||||
Dependency dependency = metadata.getDependencies().get("test");
|
Dependency dependency = metadata.getDependencies().get("test");
|
||||||
assertThat(dependency).isNotNull();
|
assertThat(dependency).isNotNull();
|
||||||
@@ -187,6 +187,20 @@ public class InitializrMetadataBuilderTests {
|
|||||||
.isEqualTo("1.0.0-beta-2423");
|
.isEqualTo("1.0.0-beta-2423");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mergeSslConfiguration() {
|
||||||
|
InitializrProperties config = load(
|
||||||
|
new ClassPathResource("application-test-default.yml"));
|
||||||
|
InitializrProperties forceSslConfig = load(
|
||||||
|
new ClassPathResource("application-test-ssl.yml"));
|
||||||
|
InitializrMetadata metadata = InitializrMetadataBuilder
|
||||||
|
.fromInitializrProperties(config)
|
||||||
|
.withInitializrProperties(forceSslConfig, true).build();
|
||||||
|
InitializrConfiguration.Env defaultEnv = new InitializrConfiguration().getEnv();
|
||||||
|
InitializrConfiguration.Env actualEnv = metadata.getConfiguration().getEnv();
|
||||||
|
assertThat(actualEnv.isForceSsl()).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addDependencyInCustomizer() {
|
public void addDependencyInCustomizer() {
|
||||||
DependencyGroup group = DependencyGroup.create("Extra");
|
DependencyGroup group = DependencyGroup.create("Extra");
|
||||||
|
@@ -2,7 +2,6 @@ initializr:
|
|||||||
env:
|
env:
|
||||||
artifactRepository: https://repo.spring.io/lib-release
|
artifactRepository: https://repo.spring.io/lib-release
|
||||||
google-analytics-tracking-code: UA-1234567-89
|
google-analytics-tracking-code: UA-1234567-89
|
||||||
forceSsl: false
|
|
||||||
fallbackApplicationName: FooBarApplication
|
fallbackApplicationName: FooBarApplication
|
||||||
invalidApplicationNames:
|
invalidApplicationNames:
|
||||||
- InvalidApplication
|
- InvalidApplication
|
||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
initializr:
|
||||||
|
env:
|
||||||
|
forceSsl: true
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"env": {
|
"env": {
|
||||||
"forceSsl": false
|
"forceSsl": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@@ -12,6 +12,7 @@ server:
|
|||||||
enabled: true
|
enabled: true
|
||||||
mime-types: application/json,text/css,text/html
|
mime-types: application/json,text/css,text/html
|
||||||
min-response-size: 2048
|
min-response-size: 2048
|
||||||
|
use-forward-headers: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
jackson:
|
jackson:
|
||||||
|
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2018 the original author or 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
|
||||||
|
*
|
||||||
|
* http://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.spring.initializr.service;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.core.AutoConfigureCache;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.boot.web.server.LocalServerPort;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.RequestEntity;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for {@link InitializrService} that force https.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "initializr.env.force-ssl=true")
|
||||||
|
@AutoConfigureCache
|
||||||
|
public class InitializrServiceHttpsTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TestRestTemplate restTemplate;
|
||||||
|
|
||||||
|
@LocalServerPort
|
||||||
|
private int localPort;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void httpCallRedirectsToHttps() {
|
||||||
|
RequestEntity<Void> request = RequestEntity.get(URI.create("/"))
|
||||||
|
.accept(MediaType.TEXT_HTML).build();
|
||||||
|
ResponseEntity<String> response = this.restTemplate.exchange(request,
|
||||||
|
String.class);
|
||||||
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FOUND);
|
||||||
|
assertThat(response.getHeaders().getLocation()).isEqualTo(
|
||||||
|
URI.create(String.format("https://localhost:%s/", this.localPort)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void securedProxiedCallDoesNotRedirect() {
|
||||||
|
RequestEntity<Void> request = RequestEntity.get(URI.create("/"))
|
||||||
|
.header("X-Forwarded-Proto", "https").accept(MediaType.TEXT_HTML).build();
|
||||||
|
ResponseEntity<String> response = this.restTemplate.exchange(request,
|
||||||
|
String.class);
|
||||||
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -28,6 +28,7 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.core.AutoConfigureCache;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
@@ -47,6 +48,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*/
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||||
|
@AutoConfigureCache
|
||||||
public class InitializrServiceSmokeTests {
|
public class InitializrServiceSmokeTests {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@@ -25,6 +25,8 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import com.samskivert.mustache.Mustache;
|
import com.samskivert.mustache.Mustache;
|
||||||
import io.spring.initializr.generator.BasicProjectRequest;
|
import io.spring.initializr.generator.BasicProjectRequest;
|
||||||
import io.spring.initializr.generator.CommandLineHelpGenerator;
|
import io.spring.initializr.generator.CommandLineHelpGenerator;
|
||||||
@@ -65,6 +67,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.servlet.resource.ResourceUrlProvider;
|
import org.springframework.web.servlet.resource.ResourceUrlProvider;
|
||||||
|
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main initializr controller provides access to the configured metadata and serves as
|
* The main initializr controller provides access to the configured metadata and serves as
|
||||||
@@ -219,7 +222,12 @@ public class MainController extends AbstractInitializrController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(path = "/", produces = "text/html")
|
@RequestMapping(path = "/", produces = "text/html")
|
||||||
public String home(Map<String, Object> model) {
|
public String home(HttpServletRequest request, Map<String, Object> model) {
|
||||||
|
if (isForceSsl() && !request.isSecure()) {
|
||||||
|
String securedUrl = ServletUriComponentsBuilder.fromCurrentRequest()
|
||||||
|
.scheme("https").build().toUriString();
|
||||||
|
return "redirect:" + securedUrl;
|
||||||
|
}
|
||||||
renderHome(model);
|
renderHome(model);
|
||||||
return "home";
|
return "home";
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,8 @@ import org.springframework.test.context.ActiveProfiles;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Integration tests with custom environment.
|
||||||
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
@ActiveProfiles({ "test-default", "test-custom-env" })
|
@ActiveProfiles({ "test-default", "test-custom-env" })
|
||||||
@@ -44,14 +46,6 @@ public class MainControllerEnvIntegrationTests
|
|||||||
assertThat(entity.getHeaders().getLocation()).isEqualTo(new URI(expected));
|
assertThat(entity.getHeaders().getLocation()).isEqualTo(new URI(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void doNotForceSsl() {
|
|
||||||
ResponseEntity<String> response = invokeHome("curl/1.2.4", "*/*");
|
|
||||||
String body = response.getBody();
|
|
||||||
assertThat(body).as("Must not force https").contains("http://start.spring.io/");
|
|
||||||
assertThat(body).as("Must not force https").doesNotContain("https://");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void generateProjectWithInvalidName() {
|
public void generateProjectWithInvalidName() {
|
||||||
downloadZip("/starter.zip?style=data-jpa&name=Invalid")
|
downloadZip("/starter.zip?style=data-jpa&name=Invalid")
|
||||||
|
@@ -305,6 +305,14 @@ public class MainControllerIntegrationTests
|
|||||||
validateCurrentMetadata(getMetadataJson());
|
validateCurrentMetadata(getMetadataJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doNotForceSslByDefault() {
|
||||||
|
ResponseEntity<String> response = invokeHome("curl/1.2.4", "*/*");
|
||||||
|
String body = response.getBody();
|
||||||
|
assertThat(body).as("Must not force https").contains("http://start.spring.io/");
|
||||||
|
assertThat(body).as("Must not force https").doesNotContain("https://");
|
||||||
|
}
|
||||||
|
|
||||||
private void validateCurlHelpContent(ResponseEntity<String> response) {
|
private void validateCurlHelpContent(ResponseEntity<String> response) {
|
||||||
validateContentType(response, MediaType.TEXT_PLAIN);
|
validateContentType(response, MediaType.TEXT_PLAIN);
|
||||||
assertThat(response.getHeaders().getFirst(HttpHeaders.ETAG)).isNotNull();
|
assertThat(response.getHeaders().getFirst(HttpHeaders.ETAG)).isNotNull();
|
||||||
|
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2018 the original author or 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
|
||||||
|
*
|
||||||
|
* http://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.spring.initializr.web.project;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import io.spring.initializr.web.AbstractInitializrControllerIntegrationTests;
|
||||||
|
import io.spring.initializr.web.mapper.InitializrMetadataVersion;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.skyscreamer.jsonassert.JSONCompareMode;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests with {@code forceSsl} enabled.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
@ActiveProfiles({ "test-default", "test-ssl" })
|
||||||
|
public class MainControllerSslIntegrationTests
|
||||||
|
extends AbstractInitializrControllerIntegrationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mainPageRedirectsToHttps() {
|
||||||
|
ResponseEntity<Void> request = execute("/", Void.class, null,
|
||||||
|
MediaType.TEXT_HTML_VALUE);
|
||||||
|
assertThat(request.getStatusCode()).isEqualTo(HttpStatus.FOUND);
|
||||||
|
// mock tests with start.spring.io host
|
||||||
|
assertThat(request.getHeaders().getLocation())
|
||||||
|
.isEqualTo(URI.create("https://start.spring.io/"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void forceSsl() {
|
||||||
|
ResponseEntity<String> response = invokeHome("curl/1.2.4", "*/*");
|
||||||
|
String body = response.getBody();
|
||||||
|
assertThat(body).as("Must force https").contains("https://start.spring.io/");
|
||||||
|
assertThat(body).as("Must force https").doesNotContain("http://");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void forceSslInMetadata() {
|
||||||
|
ResponseEntity<String> response = invokeHome(null,
|
||||||
|
"application/vnd.initializr.v2.1+json");
|
||||||
|
validateMetadata(response, InitializrMetadataVersion.V2_1.getMediaType(),
|
||||||
|
"2.1.0-ssl", JSONCompareMode.STRICT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void forceSslInMetadataV2() {
|
||||||
|
ResponseEntity<String> response = invokeHome(null,
|
||||||
|
"application/vnd.initializr.v2+json");
|
||||||
|
validateMetadata(response, InitializrMetadataVersion.V2.getMediaType(),
|
||||||
|
"2.0.0-ssl", JSONCompareMode.STRICT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -32,7 +32,7 @@
|
|||||||
"configuration": {"env": {
|
"configuration": {"env": {
|
||||||
"artifactRepository": "https://repo.spring.io/release/",
|
"artifactRepository": "https://repo.spring.io/release/",
|
||||||
"fallbackApplicationName": "Application",
|
"fallbackApplicationName": "Application",
|
||||||
"forceSsl": true,
|
"forceSsl": false,
|
||||||
"gradle": {
|
"gradle": {
|
||||||
"dependencyManagementPluginVersion": "1.0.0.RELEASE"
|
"dependencyManagementPluginVersion": "1.0.0.RELEASE"
|
||||||
},
|
},
|
||||||
|
@@ -0,0 +1,194 @@
|
|||||||
|
{
|
||||||
|
"_links": {
|
||||||
|
"maven-build": {
|
||||||
|
"href": "https://@host@/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
|
"templated": true
|
||||||
|
},
|
||||||
|
"maven-project": {
|
||||||
|
"href": "https://@host@/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
|
"templated": true
|
||||||
|
},
|
||||||
|
"gradle-build": {
|
||||||
|
"href": "https://@host@/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
|
"templated": true
|
||||||
|
},
|
||||||
|
"gradle-project": {
|
||||||
|
"href": "https://@host@/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
|
"templated": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"type": "hierarchical-multi-select",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"name": "Core",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "web",
|
||||||
|
"name": "Web",
|
||||||
|
"description": "Web dependency description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "security",
|
||||||
|
"name": "Security"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "data-jpa",
|
||||||
|
"name": "Data JPA"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "org.acme:foo",
|
||||||
|
"name": "Foo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "org.acme:bar",
|
||||||
|
"name": "Bar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "my-api",
|
||||||
|
"name": "My API"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "action",
|
||||||
|
"default": "maven-project",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "maven-build",
|
||||||
|
"name": "Maven POM",
|
||||||
|
"action": "/pom.xml",
|
||||||
|
"tags": {
|
||||||
|
"build": "maven",
|
||||||
|
"format": "build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "maven-project",
|
||||||
|
"name": "Maven Project",
|
||||||
|
"action": "/starter.zip",
|
||||||
|
"tags": {
|
||||||
|
"build": "maven",
|
||||||
|
"format": "project"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gradle-build",
|
||||||
|
"name": "Gradle Config",
|
||||||
|
"action": "/build.gradle",
|
||||||
|
"tags": {
|
||||||
|
"build": "gradle",
|
||||||
|
"format": "build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gradle-project",
|
||||||
|
"name": "Gradle Project",
|
||||||
|
"action": "/starter.zip",
|
||||||
|
"tags": {
|
||||||
|
"build": "gradle",
|
||||||
|
"format": "project"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"packaging": {
|
||||||
|
"type": "single-select",
|
||||||
|
"default": "jar",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "jar",
|
||||||
|
"name": "Jar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "war",
|
||||||
|
"name": "War"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"javaVersion": {
|
||||||
|
"type": "single-select",
|
||||||
|
"default": "1.8",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "1.6",
|
||||||
|
"name": "1.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1.7",
|
||||||
|
"name": "1.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1.8",
|
||||||
|
"name": "1.8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"language": {
|
||||||
|
"type": "single-select",
|
||||||
|
"default": "java",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "groovy",
|
||||||
|
"name": "Groovy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "java",
|
||||||
|
"name": "Java"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "kotlin",
|
||||||
|
"name": "Kotlin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"bootVersion": {
|
||||||
|
"type": "single-select",
|
||||||
|
"default": "1.1.4.RELEASE",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "1.2.0.BUILD-SNAPSHOT",
|
||||||
|
"name": "Latest SNAPSHOT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1.1.4.RELEASE",
|
||||||
|
"name": "1.1.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1.0.2.RELEASE",
|
||||||
|
"name": "1.0.2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"groupId": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "com.example"
|
||||||
|
},
|
||||||
|
"artifactId": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "demo"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "0.0.1-SNAPSHOT"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "demo"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "Demo project for Spring Boot"
|
||||||
|
},
|
||||||
|
"packageName": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "com.example.demo"
|
||||||
|
}
|
||||||
|
}
|
@@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"_links": {
|
"_links": {
|
||||||
"maven-build": {
|
"maven-build": {
|
||||||
"href": "https://@host@/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
"href": "http://@host@/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
"templated": true
|
"templated": true
|
||||||
},
|
},
|
||||||
"maven-project": {
|
"maven-project": {
|
||||||
"href": "https://@host@/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
"href": "http://@host@/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
"templated": true
|
"templated": true
|
||||||
},
|
},
|
||||||
"gradle-build": {
|
"gradle-build": {
|
||||||
"href": "https://@host@/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
"href": "http://@host@/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
"templated": true
|
"templated": true
|
||||||
},
|
},
|
||||||
"gradle-project": {
|
"gradle-project": {
|
||||||
"href": "https://@host@/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
"href": "http://@host@/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
"templated": true
|
"templated": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@@ -0,0 +1,232 @@
|
|||||||
|
{
|
||||||
|
"_links": {
|
||||||
|
"dependencies": {
|
||||||
|
"href": "https://@host@/dependencies{?bootVersion}",
|
||||||
|
"templated": true
|
||||||
|
},
|
||||||
|
"maven-build": {
|
||||||
|
"href": "https://@host@/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
|
"templated": true
|
||||||
|
},
|
||||||
|
"maven-project": {
|
||||||
|
"href": "https://@host@/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
|
"templated": true
|
||||||
|
},
|
||||||
|
"gradle-build": {
|
||||||
|
"href": "https://@host@/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
|
"templated": true
|
||||||
|
},
|
||||||
|
"gradle-project": {
|
||||||
|
"href": "https://@host@/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
|
"templated": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"type": "hierarchical-multi-select",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"name": "Core",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "web",
|
||||||
|
"name": "Web",
|
||||||
|
"description": "Web dependency description",
|
||||||
|
"_links": {
|
||||||
|
"guide": {
|
||||||
|
"href": "https://example.com/guide",
|
||||||
|
"title": "Building a RESTful Web Service"
|
||||||
|
},
|
||||||
|
"reference": {
|
||||||
|
"href": "https://example.com/doc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "security",
|
||||||
|
"name": "Security"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "data-jpa",
|
||||||
|
"name": "Data JPA"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Other",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "org.acme:foo",
|
||||||
|
"name": "Foo",
|
||||||
|
"_links": {
|
||||||
|
"guide": [
|
||||||
|
{
|
||||||
|
"href": "https://example.com/guide1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": "https://example.com/guide2",
|
||||||
|
"title": "Some guide for foo"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reference": {
|
||||||
|
"href": "https://example.com/{bootVersion}/doc",
|
||||||
|
"templated": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "org.acme:bar",
|
||||||
|
"name": "Bar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "org.acme:biz",
|
||||||
|
"name": "Biz",
|
||||||
|
"versionRange": "1.2.0.BUILD-SNAPSHOT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "org.acme:bur",
|
||||||
|
"name": "Bur",
|
||||||
|
"versionRange": "[1.1.4.RELEASE,1.2.0.BUILD-SNAPSHOT)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "my-api",
|
||||||
|
"name": "My API"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "action",
|
||||||
|
"default": "maven-project",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "maven-build",
|
||||||
|
"name": "Maven POM",
|
||||||
|
"action": "/pom.xml",
|
||||||
|
"tags": {
|
||||||
|
"build": "maven",
|
||||||
|
"format": "build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "maven-project",
|
||||||
|
"name": "Maven Project",
|
||||||
|
"action": "/starter.zip",
|
||||||
|
"tags": {
|
||||||
|
"build": "maven",
|
||||||
|
"format": "project"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gradle-build",
|
||||||
|
"name": "Gradle Config",
|
||||||
|
"action": "/build.gradle",
|
||||||
|
"tags": {
|
||||||
|
"build": "gradle",
|
||||||
|
"format": "build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gradle-project",
|
||||||
|
"name": "Gradle Project",
|
||||||
|
"action": "/starter.zip",
|
||||||
|
"tags": {
|
||||||
|
"build": "gradle",
|
||||||
|
"format": "project"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"packaging": {
|
||||||
|
"type": "single-select",
|
||||||
|
"default": "jar",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "jar",
|
||||||
|
"name": "Jar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "war",
|
||||||
|
"name": "War"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"javaVersion": {
|
||||||
|
"type": "single-select",
|
||||||
|
"default": "1.8",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "1.6",
|
||||||
|
"name": "1.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1.7",
|
||||||
|
"name": "1.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1.8",
|
||||||
|
"name": "1.8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"language": {
|
||||||
|
"type": "single-select",
|
||||||
|
"default": "java",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "groovy",
|
||||||
|
"name": "Groovy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "java",
|
||||||
|
"name": "Java"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "kotlin",
|
||||||
|
"name": "Kotlin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"bootVersion": {
|
||||||
|
"type": "single-select",
|
||||||
|
"default": "1.1.4.RELEASE",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"id": "1.2.0.BUILD-SNAPSHOT",
|
||||||
|
"name": "Latest SNAPSHOT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1.1.4.RELEASE",
|
||||||
|
"name": "1.1.4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1.0.2.RELEASE",
|
||||||
|
"name": "1.0.2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"groupId": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "com.example"
|
||||||
|
},
|
||||||
|
"artifactId": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "demo"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "0.0.1-SNAPSHOT"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "demo"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "Demo project for Spring Boot"
|
||||||
|
},
|
||||||
|
"packageName": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "com.example.demo"
|
||||||
|
}
|
||||||
|
}
|
@@ -1,23 +1,23 @@
|
|||||||
{
|
{
|
||||||
"_links": {
|
"_links": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"href": "https://@host@/dependencies{?bootVersion}",
|
"href": "http://@host@/dependencies{?bootVersion}",
|
||||||
"templated": true
|
"templated": true
|
||||||
},
|
},
|
||||||
"maven-build": {
|
"maven-build": {
|
||||||
"href": "https://@host@/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
"href": "http://@host@/pom.xml?type=maven-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
"templated": true
|
"templated": true
|
||||||
},
|
},
|
||||||
"maven-project": {
|
"maven-project": {
|
||||||
"href": "https://@host@/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
"href": "http://@host@/starter.zip?type=maven-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
"templated": true
|
"templated": true
|
||||||
},
|
},
|
||||||
"gradle-build": {
|
"gradle-build": {
|
||||||
"href": "https://@host@/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
"href": "http://@host@/build.gradle?type=gradle-build{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
"templated": true
|
"templated": true
|
||||||
},
|
},
|
||||||
"gradle-project": {
|
"gradle-project": {
|
||||||
"href": "https://@host@/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
"href": "http://@host@/starter.zip?type=gradle-project{&dependencies,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
|
||||||
"templated": true
|
"templated": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user