mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
Merge pull request #6087 from smowton/smowton/admin/rest-xss-tests
Java: Add Spring XSS tests
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@RestController
|
||||
public class SpringXSS {
|
||||
|
||||
@GetMapping
|
||||
public static ResponseEntity<String> specificContentType(boolean safeContentType, boolean chainDirectly, String userControlled) {
|
||||
|
||||
ResponseEntity.BodyBuilder builder = ResponseEntity.ok();
|
||||
|
||||
if(safeContentType) {
|
||||
if(chainDirectly) {
|
||||
return builder.contentType(MediaType.TEXT_HTML).body(userControlled); // $xss
|
||||
}
|
||||
else {
|
||||
ResponseEntity.BodyBuilder builder2 = builder.contentType(MediaType.TEXT_HTML);
|
||||
return builder2.body(userControlled); // $xss
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(chainDirectly) {
|
||||
return builder.contentType(MediaType.APPLICATION_JSON).body(userControlled); // $SPURIOUS: xss
|
||||
}
|
||||
else {
|
||||
ResponseEntity.BodyBuilder builder2 = builder.contentType(MediaType.APPLICATION_JSON);
|
||||
return builder2.body(userControlled); // $SPURIOUS: xss
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@GetMapping(value = "/xyz", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public static ResponseEntity<String> methodContentTypeSafe(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/xyz", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public static ResponseEntity<String> methodContentTypeSafePost(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/xyz", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public static ResponseEntity<String> methodContentTypeSafeRequest(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/xyz", produces = "application/json")
|
||||
public static ResponseEntity<String> methodContentTypeSafeStringLiteral(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/xyz", produces = MediaType.TEXT_HTML_VALUE)
|
||||
public static ResponseEntity<String> methodContentTypeUnsafe(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled); // $MISSING: xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/xyz", produces = "text/html")
|
||||
public static ResponseEntity<String> methodContentTypeUnsafeStringLiteral(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled); // $xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/xyz", produces = {MediaType.TEXT_HTML_VALUE, MediaType.APPLICATION_JSON_VALUE})
|
||||
public static ResponseEntity<String> methodContentTypeMaybeSafe(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled); // $xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/xyz", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public static ResponseEntity<String> methodContentTypeSafeOverriddenWithUnsafe(String userControlled) {
|
||||
return ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body(userControlled); // $MISSING: xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/xyz", produces = MediaType.TEXT_HTML_VALUE)
|
||||
public static ResponseEntity<String> methodContentTypeUnsafeOverriddenWithSafe(String userControlled) {
|
||||
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(userControlled);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/xyz", produces = {"text/html", "application/json"})
|
||||
public static ResponseEntity<String> methodContentTypeMaybeSafeStringLiterals(String userControlled, int constructionMethod) {
|
||||
// Also try out some alternative constructors for the ResponseEntity:
|
||||
switch(constructionMethod) {
|
||||
case 0:
|
||||
return ResponseEntity.ok(userControlled); // $xss
|
||||
case 1:
|
||||
return ResponseEntity.of(Optional.of(userControlled)); // $xss
|
||||
case 2:
|
||||
return ResponseEntity.ok().body(userControlled); // $xss
|
||||
case 3:
|
||||
return new ResponseEntity<String>(userControlled, HttpStatus.OK); // $xss
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
@RequestMapping(produces = {"application/json"})
|
||||
private static class ClassContentTypeSafe {
|
||||
@GetMapping(value = "/abc")
|
||||
public ResponseEntity<String> test(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled); // $SPURIOUS: xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/abc")
|
||||
public String testDirectReturn(String userControlled) {
|
||||
return userControlled; // $SPURIOUS: xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/xyz", produces = {"text/html"})
|
||||
public ResponseEntity<String> overridesWithUnsafe(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled); // $xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/abc")
|
||||
public ResponseEntity<String> overridesWithUnsafe2(String userControlled) {
|
||||
return ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body(userControlled); // $xss
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
@RequestMapping(produces = {"text/html"})
|
||||
private static class ClassContentTypeUnsafe {
|
||||
@GetMapping(value = "/abc")
|
||||
public ResponseEntity<String> test(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled); // $xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/abc")
|
||||
public String testDirectReturn(String userControlled) {
|
||||
return userControlled; // $xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/xyz", produces = {"application/json"})
|
||||
public ResponseEntity<String> overridesWithSafe(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled); // $SPURIOUS: xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/abc")
|
||||
public ResponseEntity<String> overridesWithSafe2(String userControlled) {
|
||||
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(userControlled); // $SPURIOUS: xss
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping(value = "/abc")
|
||||
public static ResponseEntity<String> entityWithNoMediaType(String userControlled) {
|
||||
return ResponseEntity.ok(userControlled); // $xss
|
||||
}
|
||||
|
||||
@GetMapping(value = "/abc")
|
||||
public static String stringWithNoMediaType(String userControlled) {
|
||||
return userControlled; // $xss
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/javax-ws-rs-api-2.1.1/
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/javax-ws-rs-api-2.1.1/:${testdir}/../../../../../stubs/springframework-5.3.8
|
||||
|
||||
@@ -62,33 +62,33 @@ public class MediaType extends MimeType implements Serializable
|
||||
public static MediaType asMediaType(MimeType p0){ return null; }
|
||||
public static MediaType parseMediaType(String p0){ return null; }
|
||||
public static MediaType valueOf(String p0){ return null; }
|
||||
public static String ALL_VALUE = null;
|
||||
public static String APPLICATION_ATOM_XML_VALUE = null;
|
||||
public static String APPLICATION_CBOR_VALUE = null;
|
||||
public static String APPLICATION_FORM_URLENCODED_VALUE = null;
|
||||
public static String APPLICATION_JSON_UTF8_VALUE = null;
|
||||
public static String APPLICATION_JSON_VALUE = null;
|
||||
public static String APPLICATION_NDJSON_VALUE = null;
|
||||
public static String APPLICATION_OCTET_STREAM_VALUE = null;
|
||||
public static String APPLICATION_PDF_VALUE = null;
|
||||
public static String APPLICATION_PROBLEM_JSON_UTF8_VALUE = null;
|
||||
public static String APPLICATION_PROBLEM_JSON_VALUE = null;
|
||||
public static String APPLICATION_PROBLEM_XML_VALUE = null;
|
||||
public static String APPLICATION_RSS_XML_VALUE = null;
|
||||
public static String APPLICATION_STREAM_JSON_VALUE = null;
|
||||
public static String APPLICATION_XHTML_XML_VALUE = null;
|
||||
public static String APPLICATION_XML_VALUE = null;
|
||||
public static String IMAGE_GIF_VALUE = null;
|
||||
public static String IMAGE_JPEG_VALUE = null;
|
||||
public static String IMAGE_PNG_VALUE = null;
|
||||
public static String MULTIPART_FORM_DATA_VALUE = null;
|
||||
public static String MULTIPART_MIXED_VALUE = null;
|
||||
public static String MULTIPART_RELATED_VALUE = null;
|
||||
public static String TEXT_EVENT_STREAM_VALUE = null;
|
||||
public static String TEXT_HTML_VALUE = null;
|
||||
public static String TEXT_MARKDOWN_VALUE = null;
|
||||
public static String TEXT_PLAIN_VALUE = null;
|
||||
public static String TEXT_XML_VALUE = null;
|
||||
public static final String ALL_VALUE = "";
|
||||
public static final String APPLICATION_ATOM_XML_VALUE = "";
|
||||
public static final String APPLICATION_CBOR_VALUE = "";
|
||||
public static final String APPLICATION_FORM_URLENCODED_VALUE = "";
|
||||
public static final String APPLICATION_JSON_UTF8_VALUE = "";
|
||||
public static final String APPLICATION_JSON_VALUE = "";
|
||||
public static final String APPLICATION_NDJSON_VALUE = "";
|
||||
public static final String APPLICATION_OCTET_STREAM_VALUE = "";
|
||||
public static final String APPLICATION_PDF_VALUE = "";
|
||||
public static final String APPLICATION_PROBLEM_JSON_UTF8_VALUE = "";
|
||||
public static final String APPLICATION_PROBLEM_JSON_VALUE = "";
|
||||
public static final String APPLICATION_PROBLEM_XML_VALUE = "";
|
||||
public static final String APPLICATION_RSS_XML_VALUE = "";
|
||||
public static final String APPLICATION_STREAM_JSON_VALUE = "";
|
||||
public static final String APPLICATION_XHTML_XML_VALUE = "";
|
||||
public static final String APPLICATION_XML_VALUE = "";
|
||||
public static final String IMAGE_GIF_VALUE = "";
|
||||
public static final String IMAGE_JPEG_VALUE = "";
|
||||
public static final String IMAGE_PNG_VALUE = "";
|
||||
public static final String MULTIPART_FORM_DATA_VALUE = "";
|
||||
public static final String MULTIPART_MIXED_VALUE = "";
|
||||
public static final String MULTIPART_RELATED_VALUE = "";
|
||||
public static final String TEXT_EVENT_STREAM_VALUE = "";
|
||||
public static final String TEXT_HTML_VALUE = "";
|
||||
public static final String TEXT_MARKDOWN_VALUE = "";
|
||||
public static final String TEXT_PLAIN_VALUE = "";
|
||||
public static final String TEXT_XML_VALUE = "";
|
||||
public static String toString(Collection<MediaType> p0){ return null; }
|
||||
public static void sortByQualityValue(List<MediaType> p0){}
|
||||
public static void sortBySpecificity(List<MediaType> p0){}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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 org.springframework.web.bind.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
@@ -6,11 +22,69 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* Annotation for mapping HTTP {@code POST} requests onto specific handler
|
||||
* methods.
|
||||
*
|
||||
* <p>Specifically, {@code @PostMapping} is a <em>composed annotation</em> that
|
||||
* acts as a shortcut for {@code @RequestMapping(method = RequestMethod.POST)}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.3
|
||||
* @see GetMapping
|
||||
* @see PutMapping
|
||||
* @see DeleteMapping
|
||||
* @see PatchMapping
|
||||
* @see RequestMapping
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public @interface PostMapping {
|
||||
|
||||
String[] value() default {};
|
||||
}
|
||||
/**
|
||||
* Alias for {@link RequestMapping#name}.
|
||||
*/
|
||||
@AliasFor(annotation = RequestMapping.class)
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* Alias for {@link RequestMapping#value}.
|
||||
*/
|
||||
@AliasFor(annotation = RequestMapping.class)
|
||||
String[] value() default {};
|
||||
|
||||
/**
|
||||
* Alias for {@link RequestMapping#path}.
|
||||
*/
|
||||
@AliasFor(annotation = RequestMapping.class)
|
||||
String[] path() default {};
|
||||
|
||||
/**
|
||||
* Alias for {@link RequestMapping#params}.
|
||||
*/
|
||||
@AliasFor(annotation = RequestMapping.class)
|
||||
String[] params() default {};
|
||||
|
||||
/**
|
||||
* Alias for {@link RequestMapping#headers}.
|
||||
*/
|
||||
@AliasFor(annotation = RequestMapping.class)
|
||||
String[] headers() default {};
|
||||
|
||||
/**
|
||||
* Alias for {@link RequestMapping#consumes}.
|
||||
*/
|
||||
@AliasFor(annotation = RequestMapping.class)
|
||||
String[] consumes() default {};
|
||||
|
||||
/**
|
||||
* Alias for {@link RequestMapping#produces}.
|
||||
*/
|
||||
@AliasFor(annotation = RequestMapping.class)
|
||||
String[] produces() default {};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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 org.springframework.web.bind.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
@@ -5,28 +21,189 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
@Target(value={ElementType.METHOD,ElementType.TYPE})
|
||||
@Retention(value=RetentionPolicy.RUNTIME)
|
||||
/**
|
||||
* Annotation for mapping web requests onto methods in request-handling classes
|
||||
* with flexible method signatures.
|
||||
*
|
||||
* <p>Both Spring MVC and Spring WebFlux support this annotation through a
|
||||
* {@code RequestMappingHandlerMapping} and {@code RequestMappingHandlerAdapter}
|
||||
* in their respective modules and package structure. For the exact list of
|
||||
* supported handler method arguments and return types in each, please use the
|
||||
* reference documentation links below:
|
||||
* <ul>
|
||||
* <li>Spring MVC
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-arguments">Method Arguments</a>
|
||||
* and
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-return-types">Return Values</a>
|
||||
* </li>
|
||||
* <li>Spring WebFlux
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-ann-arguments">Method Arguments</a>
|
||||
* and
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-ann-return-types">Return Values</a>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><strong>Note:</strong> This annotation can be used both at the class and
|
||||
* at the method level. In most cases, at the method level applications will
|
||||
* prefer to use one of the HTTP method specific variants
|
||||
* {@link GetMapping @GetMapping}, {@link PostMapping @PostMapping},
|
||||
* {@link PutMapping @PutMapping}, {@link DeleteMapping @DeleteMapping}, or
|
||||
* {@link PatchMapping @PatchMapping}.</p>
|
||||
*
|
||||
* <p><b>NOTE:</b> When using controller interfaces (e.g. for AOP proxying),
|
||||
* make sure to consistently put <i>all</i> your mapping annotations - such as
|
||||
* {@code @RequestMapping} and {@code @SessionAttributes} - on
|
||||
* the controller <i>interface</i> rather than on the implementation class.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @author Sam Brannen
|
||||
* @since 2.5
|
||||
* @see GetMapping
|
||||
* @see PostMapping
|
||||
* @see PutMapping
|
||||
* @see DeleteMapping
|
||||
* @see PatchMapping
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Mapping
|
||||
public @interface RequestMapping {
|
||||
String name() default "";
|
||||
|
||||
@AliasFor("path")
|
||||
String[] value() default {};
|
||||
/**
|
||||
* Assign a name to this mapping.
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* When used on both levels, a combined name is derived by concatenation
|
||||
* with "#" as separator.
|
||||
* @see org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder
|
||||
* @see org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
@AliasFor("value")
|
||||
String[] path() default {};
|
||||
/**
|
||||
* The primary mapping expressed by this annotation.
|
||||
* <p>This is an alias for {@link #path}. For example,
|
||||
* {@code @RequestMapping("/foo")} is equivalent to
|
||||
* {@code @RequestMapping(path="/foo")}.
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* When used at the type level, all method-level mappings inherit
|
||||
* this primary mapping, narrowing it for a specific handler method.
|
||||
* <p><strong>NOTE</strong>: A handler method that is not mapped to any path
|
||||
* explicitly is effectively mapped to an empty path.
|
||||
*/
|
||||
@AliasFor("path")
|
||||
String[] value() default {};
|
||||
|
||||
RequestMethod[] method() default {};
|
||||
/**
|
||||
* The path mapping URIs (e.g. {@code "/profile"}).
|
||||
* <p>Ant-style path patterns are also supported (e.g. {@code "/profile/**"}).
|
||||
* At the method level, relative paths (e.g. {@code "edit"}) are supported
|
||||
* within the primary mapping expressed at the type level.
|
||||
* Path mapping URIs may contain placeholders (e.g. <code>"/${profile_path}"</code>).
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* When used at the type level, all method-level mappings inherit
|
||||
* this primary mapping, narrowing it for a specific handler method.
|
||||
* <p><strong>NOTE</strong>: A handler method that is not mapped to any path
|
||||
* explicitly is effectively mapped to an empty path.
|
||||
* @since 4.2
|
||||
*/
|
||||
@AliasFor("value")
|
||||
String[] path() default {};
|
||||
|
||||
String[] params() default {};
|
||||
/**
|
||||
* The HTTP request methods to map to, narrowing the primary mapping:
|
||||
* GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* When used at the type level, all method-level mappings inherit this
|
||||
* HTTP method restriction.
|
||||
*/
|
||||
RequestMethod[] method() default {};
|
||||
|
||||
String[] headers() default {};
|
||||
/**
|
||||
* The parameters of the mapped request, narrowing the primary mapping.
|
||||
* <p>Same format for any environment: a sequence of "myParam=myValue" style
|
||||
* expressions, with a request only mapped if each such parameter is found
|
||||
* to have the given value. Expressions can be negated by using the "!=" operator,
|
||||
* as in "myParam!=myValue". "myParam" style expressions are also supported,
|
||||
* with such parameters having to be present in the request (allowed to have
|
||||
* any value). Finally, "!myParam" style expressions indicate that the
|
||||
* specified parameter is <i>not</i> supposed to be present in the request.
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* When used at the type level, all method-level mappings inherit this
|
||||
* parameter restriction.
|
||||
*/
|
||||
String[] params() default {};
|
||||
|
||||
String[] consumes() default {};
|
||||
/**
|
||||
* The headers of the mapped request, narrowing the primary mapping.
|
||||
* <p>Same format for any environment: a sequence of "My-Header=myValue" style
|
||||
* expressions, with a request only mapped if each such header is found
|
||||
* to have the given value. Expressions can be negated by using the "!=" operator,
|
||||
* as in "My-Header!=myValue". "My-Header" style expressions are also supported,
|
||||
* with such headers having to be present in the request (allowed to have
|
||||
* any value). Finally, "!My-Header" style expressions indicate that the
|
||||
* specified header is <i>not</i> supposed to be present in the request.
|
||||
* <p>Also supports media type wildcards (*), for headers such as Accept
|
||||
* and Content-Type. For instance,
|
||||
* <pre class="code">
|
||||
* @RequestMapping(value = "/something", headers = "content-type=text/*")
|
||||
* </pre>
|
||||
* will match requests with a Content-Type of "text/html", "text/plain", etc.
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* When used at the type level, all method-level mappings inherit this
|
||||
* header restriction.
|
||||
* @see org.springframework.http.MediaType
|
||||
*/
|
||||
String[] headers() default {};
|
||||
|
||||
/**
|
||||
* Narrows the primary mapping by media types that can be consumed by the
|
||||
* mapped handler. Consists of one or more media types one of which must
|
||||
* match to the request {@code Content-Type} header. Examples:
|
||||
* <pre class="code">
|
||||
* consumes = "text/plain"
|
||||
* consumes = {"text/plain", "application/*"}
|
||||
* consumes = MediaType.TEXT_PLAIN_VALUE
|
||||
* </pre>
|
||||
* Expressions can be negated by using the "!" operator, as in
|
||||
* "!text/plain", which matches all requests with a {@code Content-Type}
|
||||
* other than "text/plain".
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* If specified at both levels, the method level consumes condition overrides
|
||||
* the type level condition.
|
||||
* @see org.springframework.http.MediaType
|
||||
* @see javax.servlet.http.HttpServletRequest#getContentType()
|
||||
*/
|
||||
String[] consumes() default {};
|
||||
|
||||
/**
|
||||
* Narrows the primary mapping by media types that can be produced by the
|
||||
* mapped handler. Consists of one or more media types one of which must
|
||||
* be chosen via content negotiation against the "acceptable" media types
|
||||
* of the request. Typically those are extracted from the {@code "Accept"}
|
||||
* header but may be derived from query parameters, or other. Examples:
|
||||
* <pre class="code">
|
||||
* produces = "text/plain"
|
||||
* produces = {"text/plain", "application/*"}
|
||||
* produces = MediaType.TEXT_PLAIN_VALUE
|
||||
* produces = "text/plain;charset=UTF-8"
|
||||
* </pre>
|
||||
* <p>If a declared media type contains a parameter (e.g. "charset=UTF-8",
|
||||
* "type=feed", "type=entry") and if a compatible media type from the request
|
||||
* has that parameter too, then the parameter values must match. Otherwise
|
||||
* if the media type from the request does not contain the parameter, it is
|
||||
* assumed the client accepts any value.
|
||||
* <p>Expressions can be negated by using the "!" operator, as in "!text/plain",
|
||||
* which matches all requests with a {@code Accept} other than "text/plain".
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* If specified at both levels, the method level produces condition overrides
|
||||
* the type level condition.
|
||||
* @see org.springframework.http.MediaType
|
||||
*/
|
||||
String[] produces() default {};
|
||||
|
||||
String[] produces() default {};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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 org.springframework.web.bind.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
/**
|
||||
* A convenience annotation that is itself annotated with
|
||||
* {@link Controller @Controller} and {@link ResponseBody @ResponseBody}.
|
||||
* <p>
|
||||
* Types that carry this annotation are treated as controllers where
|
||||
* {@link RequestMapping @RequestMapping} methods assume
|
||||
* {@link ResponseBody @ResponseBody} semantics by default.
|
||||
*
|
||||
* <p><b>NOTE:</b> {@code @RestController} is processed if an appropriate
|
||||
* {@code HandlerMapping}-{@code HandlerAdapter} pair is configured such as the
|
||||
* {@code RequestMappingHandlerMapping}-{@code RequestMappingHandlerAdapter}
|
||||
* pair which are the default in the MVC Java config and the MVC namespace.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Sam Brannen
|
||||
* @since 4.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Controller
|
||||
@ResponseBody
|
||||
public @interface RestController {
|
||||
|
||||
/**
|
||||
* The value may indicate a suggestion for a logical component name,
|
||||
* to be turned into a Spring bean in case of an autodetected component.
|
||||
* @return the suggested component name, if any (or empty String otherwise)
|
||||
* @since 4.0.1
|
||||
*/
|
||||
@AliasFor(annotation = Controller.class)
|
||||
String value() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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 org.springframework.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a MIME Type, as originally defined in RFC 2046 and subsequently
|
||||
* used in other Internet protocols including HTTP.
|
||||
*
|
||||
* <p>This class, however, does not contain support for the q-parameters used
|
||||
* in HTTP content negotiation. Those can be found in the subclass
|
||||
* {@code org.springframework.http.MediaType} in the {@code spring-web} module.
|
||||
*
|
||||
* <p>Consists of a {@linkplain #getType() type} and a {@linkplain #getSubtype() subtype}.
|
||||
* Also has functionality to parse MIME Type values from a {@code String} using
|
||||
* {@link #valueOf(String)}. For more parsing options see {@link MimeTypeUtils}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Sam Brannen
|
||||
* @since 4.0
|
||||
* @see MimeTypeUtils
|
||||
*/
|
||||
public class MimeType implements Comparable<MimeType>, Serializable {
|
||||
|
||||
protected static final String WILDCARD_TYPE = "";
|
||||
|
||||
/**
|
||||
* Create a new {@code MimeType} for the given primary type.
|
||||
* <p>The {@linkplain #getSubtype() subtype} is set to <code>"*"</code>,
|
||||
* and the parameters are empty.
|
||||
* @param type the primary type
|
||||
* @throws IllegalArgumentException if any of the parameters contains illegal characters
|
||||
*/
|
||||
public MimeType(String type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code MimeType} for the given primary type and subtype.
|
||||
* <p>The parameters are empty.
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @throws IllegalArgumentException if any of the parameters contains illegal characters
|
||||
*/
|
||||
public MimeType(String type, String subtype) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code MimeType} for the given type, subtype, and character set.
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @param charset the character set
|
||||
* @throws IllegalArgumentException if any of the parameters contains illegal characters
|
||||
*/
|
||||
public MimeType(String type, String subtype, Charset charset) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy-constructor that copies the type, subtype, parameters of the given {@code MimeType},
|
||||
* and allows to set the specified character set.
|
||||
* @param other the other MimeType
|
||||
* @param charset the character set
|
||||
* @throws IllegalArgumentException if any of the parameters contains illegal characters
|
||||
* @since 4.3
|
||||
*/
|
||||
public MimeType(MimeType other, Charset charset) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy-constructor that copies the type and subtype of the given {@code MimeType},
|
||||
* and allows for different parameter.
|
||||
* @param other the other MimeType
|
||||
* @param parameters the parameters (may be {@code null})
|
||||
* @throws IllegalArgumentException if any of the parameters contains illegal characters
|
||||
*/
|
||||
public MimeType(MimeType other, @Nullable Map<String, String> parameters) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code MimeType} for the given type, subtype, and parameters.
|
||||
* @param type the primary type
|
||||
* @param subtype the subtype
|
||||
* @param parameters the parameters (may be {@code null})
|
||||
* @throws IllegalArgumentException if any of the parameters contains illegal characters
|
||||
*/
|
||||
public MimeType(String type, String subtype, @Nullable Map<String, String> parameters) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy-constructor that copies the type, subtype and parameters of the given {@code MimeType},
|
||||
* skipping checks performed in other constructors.
|
||||
* @param other the other MimeType
|
||||
* @since 5.3
|
||||
*/
|
||||
protected MimeType(MimeType other) {
|
||||
}
|
||||
|
||||
protected void checkParameters(String parameter, String value) {
|
||||
}
|
||||
|
||||
protected String unquote(String s) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the {@linkplain #getType() type} is the wildcard character
|
||||
* <code>*</code> or not.
|
||||
*/
|
||||
public boolean isWildcardType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the {@linkplain #getSubtype() subtype} is the wildcard
|
||||
* character <code>*</code> or the wildcard character followed by a suffix
|
||||
* (e.g. <code>*+xml</code>).
|
||||
* @return whether the subtype is a wildcard
|
||||
*/
|
||||
public boolean isWildcardSubtype() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this MIME Type is concrete, i.e. whether neither the type
|
||||
* nor the subtype is a wildcard character <code>*</code>.
|
||||
* @return whether this MIME Type is concrete
|
||||
*/
|
||||
public boolean isConcrete() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the primary type.
|
||||
*/
|
||||
public String getType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subtype.
|
||||
*/
|
||||
public String getSubtype() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subtype suffix as defined in RFC 6839.
|
||||
* @since 5.3
|
||||
*/
|
||||
@Nullable
|
||||
public String getSubtypeSuffix() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the character set, as indicated by a {@code charset} parameter, if any.
|
||||
* @return the character set, or {@code null} if not available
|
||||
* @since 4.3
|
||||
*/
|
||||
@Nullable
|
||||
public Charset getCharset() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a generic parameter value, given a parameter name.
|
||||
* @param name the parameter name
|
||||
* @return the parameter value, or {@code null} if not present
|
||||
*/
|
||||
@Nullable
|
||||
public String getParameter(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all generic parameter values.
|
||||
* @return a read-only map (possibly empty, never {@code null})
|
||||
*/
|
||||
public Map<String, String> getParameters() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether this MIME Type includes the given MIME Type.
|
||||
* <p>For instance, {@code text/*} includes {@code text/plain} and {@code text/html},
|
||||
* and {@code application/*+xml} includes {@code application/soap+xml}, etc.
|
||||
* This method is <b>not</b> symmetric.
|
||||
* @param other the reference MIME Type with which to compare
|
||||
* @return {@code true} if this MIME Type includes the given MIME Type;
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public boolean includes(@Nullable MimeType other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether this MIME Type is compatible with the given MIME Type.
|
||||
* <p>For instance, {@code text/*} is compatible with {@code text/plain},
|
||||
* {@code text/html}, and vice versa. In effect, this method is similar to
|
||||
* {@link #includes}, except that it <b>is</b> symmetric.
|
||||
* @param other the reference MIME Type with which to compare
|
||||
* @return {@code true} if this MIME Type is compatible with the given MIME Type;
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public boolean isCompatibleWith(@Nullable MimeType other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link #equals(Object)} but based on the type and subtype
|
||||
* only, i.e. ignoring parameters.
|
||||
* @param other the other mime type to compare to
|
||||
* @return whether the two mime types have the same type and subtype
|
||||
* @since 5.1.4
|
||||
*/
|
||||
public boolean equalsTypeAndSubtype(@Nullable MimeType other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlike {@link Collection#contains(Object)} which relies on
|
||||
* {@link MimeType#equals(Object)}, this method only checks the type and the
|
||||
* subtype, but otherwise ignores parameters.
|
||||
* @param mimeTypes the list of mime types to perform the check against
|
||||
* @return whether the list contains the given mime type
|
||||
* @since 5.1.4
|
||||
*/
|
||||
public boolean isPresentIn(Collection<? extends MimeType> mimeTypes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the parameters in this {@code MimeType} and the supplied
|
||||
* {@code MimeType} are equal, performing case-insensitive comparisons
|
||||
* for {@link Charset Charsets}.
|
||||
* @since 4.2
|
||||
*/
|
||||
private boolean parametersAreEqual(MimeType other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void appendTo(StringBuilder builder) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this MIME Type to another alphabetically.
|
||||
* @param other the MIME Type to compare to
|
||||
* @see MimeTypeUtils#sortBySpecificity(List)
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(MimeType other) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given String value into a {@code MimeType} object,
|
||||
* with this method name following the 'valueOf' naming convention
|
||||
* (as supported by {@link org.springframework.core.convert.ConversionService}.
|
||||
* @see MimeTypeUtils#parseMimeType(String)
|
||||
*/
|
||||
public static MimeType valueOf(String value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator to sort {@link MimeType MimeTypes} in order of specificity.
|
||||
*
|
||||
* @param <T> the type of mime types that may be compared by this comparator
|
||||
*/
|
||||
public static class SpecificityComparator<T extends MimeType> implements Comparator<T> {
|
||||
|
||||
@Override
|
||||
public int compare(T mimeType1, T mimeType2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected int compareParameters(T mimeType1, T mimeType2) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user