Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.SpecVersion;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.configuration.SpringDocConfiguration;
import org.springdoc.core.properties.SpringDocConfigProperties.ApiDocs.OpenApiVersion;
import org.springdoc.core.utils.Constants;
Expand All @@ -44,6 +47,8 @@
import org.springframework.context.annotation.Lazy;
import org.springframework.http.MediaType;

import static org.springdoc.core.utils.Constants.DEFAULT_TITLE;
import static org.springdoc.core.utils.Constants.DEFAULT_VERSION;
import static org.springdoc.core.utils.Constants.DEFAULT_WEB_JARS_PREFIX_URL;
import static org.springdoc.core.utils.Constants.SPRINGDOC_ENABLED;

Expand Down Expand Up @@ -1451,6 +1456,11 @@ public static class ApiDocs {
*/
private Groups groups = new Groups();

/**
* The Info.
*/
private Info info = new Info();

/**
* The OpenAPI version.
*/
Expand Down Expand Up @@ -1510,6 +1520,24 @@ public void setGroups(Groups groups) {
this.groups = groups;
}

/**
* Gets info.
*
* @return the info
*/
public Info getInfo() {
return info;
}

/**
* Sets info.
*
* @param info the info
*/
public void setInfo(Info info) {
this.info = info;
}

/**
* Is resolve schema properties boolean.
*
Expand Down Expand Up @@ -1947,4 +1975,194 @@ public int hashCode() {
return Objects.hash(group);
}
}

/**
* The type Info.
*/
public static class Info {

/**
* The Title.
*/
private String title = DEFAULT_TITLE;

/**
* The Description.
*/
private String description;

/**
* The Terms of service.
*/
private String termsOfService;

/**
* The Contact.
*/
private Contact contact;

/**
* The License.
*/
private License license;

/**
* The Version.
*/
private String version = DEFAULT_VERSION;

/**
* The Extensions.
*/
private Map<String, Object> extensions;

/**
* The Summary.
*/
private String summary;

/**
* Gets title.
*
* @return the title
*/
public String getTitle() {
return title;
}

/**
* Sets title.
*
* @param title the title
*/
public void setTitle(String title) {
this.title = title;
}

/**
* Gets description.
*
* @return the description
*/
public String getDescription() {
return description;
}

/**
* Sets description.
*
* @param description the description
*/
public void setDescription(String description) {
this.description = description;
}

/**
* Gets terms of service.
*
* @return the terms of service
*/
public String getTermsOfService() {
return termsOfService;
}

/**
* Sets terms of service.
*
* @param termsOfService the terms of service
*/
public void setTermsOfService(String termsOfService) {
this.termsOfService = termsOfService;
}

/**
* Gets contact.
*
* @return the contact
*/
public Contact getContact() {
return contact;
}

/**
* Sets contact.
*
* @param contact the contact
*/
public void setContact(Contact contact) {
this.contact = contact;
}

/**
* Gets license.
*
* @return the license
*/
public License getLicense() {
return license;
}

/**
* Sets license.
*
* @param license the license
*/
public void setLicense(License license) {
this.license = license;
}

/**
* Gets version.
*
* @return the version
*/
public String getVersion() {
return version;
}

/**
* Sets version.
*
* @param version the version
*/
public void setVersion(String version) {
this.version = version;
}

/**
* Gets extensions.
*
* @return the extensions
*/
public Map<String, Object> getExtensions() {
return extensions;
}

/**
* Sets extensions.
*
* @param extensions the extensions
*/
public void setExtensions(Map<String, Object> extensions) {
this.extensions = extensions;
}

/**
* Gets summary.
*
* @return the summary
*/
public String getSummary() {
return summary;
}

/**
* Sets summary.
*
* @param summary the summary
*/
public void setSummary(String summary) {
this.summary = summary;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,15 @@ public OpenAPI build(Locale locale) {
}
// Set default info
else if (calculatedOpenAPI != null && calculatedOpenAPI.getInfo() == null) {
Info infos = new Info().title(DEFAULT_TITLE).version(DEFAULT_VERSION);
Info infos = new Info()
.title(springDocConfigProperties.getApiDocs().getInfo().getTitle())
.description(springDocConfigProperties.getApiDocs().getInfo().getDescription())
.termsOfService(springDocConfigProperties.getApiDocs().getInfo().getTermsOfService())
.contact(springDocConfigProperties.getApiDocs().getInfo().getContact())
.license(springDocConfigProperties.getApiDocs().getInfo().getLicense())
.version(springDocConfigProperties.getApiDocs().getInfo().getVersion())
.extensions(springDocConfigProperties.getApiDocs().getInfo().getExtensions())
.summary(springDocConfigProperties.getApiDocs().getInfo().getSummary());
calculatedOpenAPI.setInfo(infos);
}
// Set default mappings
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
*
* *
* * *
* * * *
* * * * *
* * * * * * Copyright 2019-2025 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
* * * * * *
* * * * * * 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 test.org.springdoc.api.v31.app250;

import org.junit.jupiter.api.Test;
import org.springdoc.core.utils.Constants;
import test.org.springdoc.api.v31.AbstractSpringDocTest;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.test.context.TestPropertySource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
* Tests loading OpenAPI info metadata from YAML configuration.
*/
@TestPropertySource(properties = "spring.config.additional-location=classpath:/application-openapi-info.yml")
class OpenApiInfoFromYamlPropertiesTest extends AbstractSpringDocTest {

/**
* Verifies the configured info block is propagated to the generated OpenAPI document.
*
* @throws Exception the exception
*/
@Test
@Override
protected void testApp() throws Exception {
mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL))
.andExpect(status().isOk())
.andExpect(jsonPath("$.info.title", is("Configured API")))
.andExpect(jsonPath("$.info.description", is("Configured via YAML")))
.andExpect(jsonPath("$.info.termsOfService", is("https://example.org/terms")))
.andExpect(jsonPath("$.info.summary", is("High level summary")))
.andExpect(jsonPath("$.info.version", is("9.9.9")))
.andExpect(jsonPath("$.info.contact.name", is("Example Support")))
.andExpect(jsonPath("$.info.contact.email", is("support@example.org")))
.andExpect(jsonPath("$.info.contact.url", is("https://example.org/support")))
.andExpect(jsonPath("$.info.license.name", is("Example License")))
.andExpect(jsonPath("$.info.license.url", is("https://example.org/license")))
.andExpect(jsonPath("$.info['x-company']", is("Example Corp")))
.andExpect(jsonPath("$.info['x-service-tier']", is("gold")));
}

/**
* Minimal application with one endpoint to ensure the OpenAPI doc is generated.
*/
@SpringBootApplication
@RestController
static class SpringDocTestApp {

/**
* Sample endpoint to register at least one route.
*
* @return the greeting
*/
@GetMapping("/greetings")
public String greetings() {
return "hello";
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
springdoc:
api-docs:
info:
title: Configured API
description: Configured via YAML
terms-of-service: https://example.org/terms
summary: High level summary
version: 9.9.9
contact:
name: Example Support
url: https://example.org/support
email: support@example.org
license:
name: Example License
url: https://example.org/license
extensions:
x-company: Example Corp
x-service-tier: gold