DATAREST-1552 - Removed deprecated HAL Browser module.
This commit is contained in:
3
pom.xml
3
pom.xml
@@ -21,7 +21,6 @@
|
||||
<module>spring-data-rest-core</module>
|
||||
<module>spring-data-rest-webmvc</module>
|
||||
<module>spring-data-rest-distribution</module>
|
||||
<module>spring-data-rest-hal-browser</module>
|
||||
<module>spring-data-rest-hal-explorer</module>
|
||||
</modules>
|
||||
|
||||
@@ -77,7 +76,7 @@
|
||||
<module>spring-data-rest-core</module>
|
||||
<module>spring-data-rest-webmvc</module>
|
||||
<module>spring-data-rest-distribution</module>
|
||||
<module>spring-data-rest-hal-browser</module>
|
||||
<module>spring-data-rest-hal-explorer</module>
|
||||
<module>spring-data-rest-tests</module>
|
||||
</modules>
|
||||
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-rest-parent</artifactId>
|
||||
<version>3.4.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>spring-data-rest-hal-browser</artifactId>
|
||||
|
||||
<name>Spring Data REST - HAL Browser</name>
|
||||
|
||||
<properties>
|
||||
<browser.version>ad9b865</browser.version>
|
||||
<json-editor.version>0.7.21</json-editor.version>
|
||||
<java-module-name>spring.data.rest.hal.browser</java-module-name>
|
||||
|
||||
<!--
|
||||
Skip Javadoc as there's no public code to document
|
||||
and this causes the Javadoc generation to fail otherwise.
|
||||
-->
|
||||
<maven.javadoc.skip>true</maven.javadoc.skip>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-data-rest-webmvc</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>hal-browser</artifactId>
|
||||
<version>${browser.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>json-editor</artifactId>
|
||||
<version>${json-editor.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>empty-javadoc-jar</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>javadoc</classifier>
|
||||
<classesDirectory>${basedir}/javadoc</classesDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack-hal-browser</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>hal-browser</artifactId>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<outputDirectory>${project.build.directory}/hal-browser</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>unpack-json-editor</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>json-editor</artifactId>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<outputDirectory>${project.build.directory}/json-editor</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<target>
|
||||
<copy todir="${project.build.outputDirectory}/META-INF/spring-data-rest/hal-browser">
|
||||
<fileset dir="${project.build.directory}/hal-browser/META-INF/resources/webjars/hal-browser/${browser.version}" />
|
||||
</copy>
|
||||
<copy todir="${project.build.outputDirectory}/META-INF/spring-data-rest/hal-browser/vendor/js">
|
||||
<fileset dir="${project.build.directory}/json-editor/META-INF/resources/webjars/json-editor/${json-editor.version}" />
|
||||
</copy>
|
||||
<copy file="${project.build.outputDirectory}/META-INF/spring-data-rest/hal-browser/browser.html"
|
||||
tofile="${project.build.outputDirectory}/META-INF/spring-data-rest/hal-browser/index.html" />
|
||||
<replace file="${project.build.outputDirectory}/META-INF/spring-data-rest/hal-browser/index.html">
|
||||
<replacefilter>
|
||||
<replacetoken><![CDATA[</body>]]></replacetoken>
|
||||
<replacevalue><![CDATA[
|
||||
<script id="dynamic-request-template" type="text/template">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Create/Update</h3>
|
||||
</div>
|
||||
|
||||
<form class="non-safe" action="<%= href %>">
|
||||
<div class="modal-body" style="padding-top: 0px">
|
||||
<div id="jsoneditor"></div>
|
||||
|
||||
<div class="well well-small" style="padding-bottom: 0px;">
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
<div class="control-group">
|
||||
<label class="control-label" style="display: inline-block; font-weight: bold;">Action:</label>
|
||||
<input name="method" type="text" class="method controls" style="width: 98%" value="POST" />
|
||||
<input name="url" type="text" class="url controls" style="width: 98%" value="<%= href %>" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Make Request</button>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
|
||||
<script src="vendor/js/jsoneditor.js"></script>
|
||||
<script src="js/CustomPostForm.js"></script>
|
||||
|
||||
</body>]]>
|
||||
</replacevalue>
|
||||
</replacefilter>
|
||||
</replace>
|
||||
<replace file="${project.build.outputDirectory}/META-INF/spring-data-rest/hal-browser/index.html">
|
||||
<replacefilter>
|
||||
<replacetoken>The HAL Browser</replacetoken>
|
||||
<replacevalue>The HAL Browser (for Spring Data REST)</replacevalue>
|
||||
</replacefilter>
|
||||
</replace>
|
||||
<delete file="${project.build.outputDirectory}/META-INF/spring-data-rest/hal-browser/browser.html" />
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-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.data.rest.webmvc.halbrowser;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.data.rest.webmvc.BasePathAwareController;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
|
||||
/**
|
||||
* Controller with a few convenience redirects to expose the HAL browser shipped as static content.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @soundtrack Miles Davis - So what (Kind of blue)
|
||||
*/
|
||||
@Slf4j
|
||||
@BasePathAwareController
|
||||
class HalBrowser {
|
||||
|
||||
static final String BROWSER = "/browser";
|
||||
static final String INDEX = "/index.html";
|
||||
|
||||
HalBrowser() {
|
||||
LOG.warn("---");
|
||||
LOG.warn(
|
||||
"Spring Data REST HAL Browser is deprecated! Prefer the HAL Explorer (artifactId: spring-data-rest-hal-explorer)!");
|
||||
LOG.warn("---");
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects requests to the API root asking for HTML to the HAL browser.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(path = { "/", "" }, produces = MediaType.TEXT_HTML_VALUE)
|
||||
View index(HttpServletRequest request) {
|
||||
return getRedirectView(request, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to the actual {@code index.html}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(path = BROWSER)
|
||||
View browser(HttpServletRequest request) {
|
||||
return getRedirectView(request, request.getRequestURI().endsWith(BROWSER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the View to redirect to to access the HAL browser.
|
||||
*
|
||||
* @param request must not be {@literal null}.
|
||||
* @param browserRelative
|
||||
* @return
|
||||
*/
|
||||
private View getRedirectView(HttpServletRequest request, boolean browserRelative) {
|
||||
|
||||
ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromRequest(request);
|
||||
|
||||
UriComponents components = builder.build();
|
||||
String path = components.getPath() == null ? "" : components.getPath();
|
||||
|
||||
if (!browserRelative) {
|
||||
builder.path(BROWSER);
|
||||
}
|
||||
|
||||
builder.path(INDEX);
|
||||
builder.fragment(browserRelative ? path.substring(0, path.lastIndexOf(BROWSER)) : path);
|
||||
|
||||
return new RedirectView(builder.build().toUriString());
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-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.data.rest.webmvc.halbrowser;
|
||||
|
||||
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.webmvc.config.StaticResourceProvider;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
|
||||
/**
|
||||
* {@link StaticResourceProvider} to expose the HAL Browser WebJar content via a static resource route.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @since 3.2
|
||||
* @soundtrack Tedeschi Trucks Band - Signs, High Times (Signs)
|
||||
*/
|
||||
class HalBrowserConfiguration implements StaticResourceProvider {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.config.StaticResourceProvider#customizeResources(org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry, org.springframework.data.rest.core.config.RepositoryRestConfiguration)
|
||||
*/
|
||||
@Override
|
||||
public void customizeResources(ResourceHandlerRegistry registry, RepositoryRestConfiguration configuration) {
|
||||
|
||||
String basePath = configuration.getBasePath().toString().concat(HalBrowser.BROWSER);
|
||||
String rootLocation = "classpath:META-INF/spring-data-rest/hal-browser/";
|
||||
|
||||
registry.addResourceHandler(basePath.concat("/**")).addResourceLocations(rootLocation);
|
||||
}
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
/**
|
||||
* Custom Backbone view that uses JSON Schema metadata to create pop-up dialog with actual field names instead of
|
||||
* asking user to input raw JSON.
|
||||
*
|
||||
* NOTE: Because JSON Schema lists all properties, including those that are links, they have to be filtered out.
|
||||
* Links have to be set via a PUT operation with the proper media type.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Gregory Frank
|
||||
* @since 2.4
|
||||
* @see DATAREST-627, DATAREST-1077
|
||||
*/
|
||||
/* jshint strict: true */
|
||||
/* globals HAL, Backbone, _, $, window, jqxhr */
|
||||
|
||||
'use strict';
|
||||
|
||||
var CustomPostForm = Backbone.View.extend({
|
||||
initialize: function (opts) {
|
||||
this.href = opts.href.split('{')[0];
|
||||
this.vent = opts.vent;
|
||||
_.bindAll(this, 'createNewResource');
|
||||
},
|
||||
|
||||
events: {
|
||||
'submit form': 'createNewResource'
|
||||
},
|
||||
|
||||
className: 'modal fade',
|
||||
|
||||
/**
|
||||
* Perform a POST/PUT operation on the resource.
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
createNewResource: function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var self = this;
|
||||
|
||||
var opts = {
|
||||
url: this.$('.url').val(),
|
||||
headers: _.defaults({'Content-Type': 'application/json'}, HAL.client.getHeaders()),
|
||||
method: this.$('.method').val(),
|
||||
data: this.getNewResourceData()
|
||||
};
|
||||
|
||||
HAL.client.request(opts).done(function (response) {
|
||||
self.vent.trigger('response', {resource: response, jqxhr: jqxhr});
|
||||
}).fail(function (e) {
|
||||
self.vent.trigger('fail-response', {jqxhr: jqxhr});
|
||||
}).always(function (e) {
|
||||
self.vent.trigger('response-headers', {jqxhr: jqxhr});
|
||||
window.location.hash = 'NON-GET:' + opts.url;
|
||||
});
|
||||
|
||||
this.$el.modal('hide');
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the dialog after fetching the resource's JSON Schema metadata. If no metadata is available, use the
|
||||
* fallback editor.
|
||||
*
|
||||
* @param opts
|
||||
* @returns {CustomPostForm}
|
||||
*/
|
||||
render: function (opts) {
|
||||
var self = this;
|
||||
|
||||
try {
|
||||
HAL.client.request({
|
||||
method: 'HEAD',
|
||||
headers: HAL.client.getHeaders(),
|
||||
url: this.href
|
||||
}).done(function (message, text, jqXHR) {
|
||||
self.$el.html(self.template({href: self.href}));
|
||||
|
||||
try {
|
||||
var hal = self.w3cLinksToHalLinks(jqXHR.getResponseHeader('Link'));
|
||||
|
||||
HAL.client.request({
|
||||
method: 'GET',
|
||||
url: hal._links.profile.href,
|
||||
headers: _.defaults({'Accept': 'application/schema+json'}, HAL.client.getHeaders())
|
||||
}).done(function (schema) {
|
||||
self.loadJsonEditor(schema);
|
||||
});
|
||||
} catch (e) {
|
||||
self.loadFallbackEditor();
|
||||
}
|
||||
|
||||
self.$el.modal();
|
||||
});
|
||||
} catch (e) {
|
||||
self.loadFallbackEditor();
|
||||
self.$el.modal();
|
||||
}
|
||||
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the JSON Schema-driven editor.
|
||||
*
|
||||
* @see https://github.com/jdorn/json-editor
|
||||
*/
|
||||
loadJsonEditor: function (schema) {
|
||||
var self = this;
|
||||
|
||||
/**
|
||||
* Remove URI-based fields since this dialog doesn't handle relationships.
|
||||
*/
|
||||
Object.keys(schema.properties).forEach(function (property) {
|
||||
if (schema.properties[property].hasOwnProperty('format') &&
|
||||
schema.properties[property].format === 'uri') {
|
||||
delete schema.properties[property];
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* See https://github.com/jdorn/json-editor#options for more customizing options.
|
||||
*/
|
||||
this.editor = new window.JSONEditor(this.$('#jsoneditor')[0], {
|
||||
theme: 'bootstrap2',
|
||||
schema: schema,
|
||||
disable_collapse: true,
|
||||
disable_edit_json: true,
|
||||
disable_properties: true
|
||||
});
|
||||
|
||||
this.getNewResourceData = function() {
|
||||
return JSON.stringify(self.editor.getValue());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Load fallback editor that doesn't depend on any form of metadata.
|
||||
*/
|
||||
loadFallbackEditor: function () {
|
||||
var editor = this.$('#jsoneditor');
|
||||
|
||||
editor.append($('<h4>' + this.href + '</h4>'));
|
||||
|
||||
var inputBox = $('<textarea name="body" class="body" style="height: 200px">{\n}</textarea>');
|
||||
editor.append(inputBox);
|
||||
|
||||
this.getNewResourceData = function() {
|
||||
return inputBox.val();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert a W3C link header into a HAL-based set of _links.
|
||||
*
|
||||
* e.g.
|
||||
* <http://localhost:8080/persons>; rel="persons",<http://localhost:8080/profile/persons>; rel="profile"
|
||||
* to
|
||||
* {
|
||||
* _links: {
|
||||
* persons: {
|
||||
* href: http://localhost:8080/persons
|
||||
* },
|
||||
* profile: {
|
||||
* href: http://localhost:8080/profile/persons
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @param linkHeader - HTTP Response header containing a list of W3C compliant links with rels.
|
||||
* @see https://www.w3.org/wiki/LinkHeader
|
||||
*/
|
||||
w3cLinksToHalLinks: function (linkHeader) {
|
||||
var w3cLinks = linkHeader.split(',');
|
||||
|
||||
var halLinks = {_links: {}};
|
||||
|
||||
w3cLinks.forEach(function (w3cLink) {
|
||||
var parts = w3cLink.split(';');
|
||||
|
||||
var hrefWrappedWithBrackets = parts[0];
|
||||
var href = hrefWrappedWithBrackets.slice(1, parts[0].length - 1);
|
||||
|
||||
var w3cRel = parts[1];
|
||||
var relWrappedWithQuotes = w3cRel.split('=')[1];
|
||||
var rel = relWrappedWithQuotes.slice(1, relWrappedWithQuotes.length - 1);
|
||||
|
||||
halLinks._links[rel] = { "href": href };
|
||||
});
|
||||
|
||||
return halLinks;
|
||||
},
|
||||
|
||||
/**
|
||||
* Look up the HTML template.
|
||||
*/
|
||||
template: _.template($('#dynamic-request-template').html())
|
||||
});
|
||||
|
||||
/**
|
||||
* Inject the form into the HAL Browser.
|
||||
*/
|
||||
HAL.customPostForm = CustomPostForm;
|
||||
@@ -1 +0,0 @@
|
||||
org.springframework.data.rest.webmvc.config.StaticResourceProvider=org.springframework.data.rest.webmvc.halbrowser.HalBrowserConfiguration
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-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.data.rest.webmvc.halbrowser;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link HalBrowser}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @soundtrack Miles Davis - Blue in green (Kind of blue)
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
public class HalBrowserIntegrationTests {
|
||||
|
||||
static final String BASE_PATH = "/api";
|
||||
static final String BROWSER_INDEX = "/browser/index.html";
|
||||
static final String TARGET = BASE_PATH.concat(BROWSER_INDEX).concat("#").concat(BASE_PATH);
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
static class TestConfiguration extends RepositoryRestMvcConfiguration {
|
||||
|
||||
public TestConfiguration(ApplicationContext context, ObjectFactory<ConversionService> conversionService) {
|
||||
super(context, conversionService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
RepositoryRestConfigurer configExtension() {
|
||||
return RepositoryRestConfigurer.withConfig(config -> config.setBasePath(BASE_PATH));
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired WebApplicationContext context;
|
||||
|
||||
MockMvc mvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mvc = MockMvcBuilders.webAppContextSetup(context).//
|
||||
defaultRequest(get(BASE_PATH).accept(MediaType.TEXT_HTML)).build();
|
||||
}
|
||||
|
||||
@Test // DATAREST-293
|
||||
public void exposesJsonUnderApiRootByDefault() throws Exception {
|
||||
|
||||
mvc.perform(get(BASE_PATH).accept(MediaType.ALL)).//
|
||||
andExpect(status().isOk()).//
|
||||
andExpect(header().string(HttpHeaders.CONTENT_TYPE, startsWith(MediaTypes.HAL_JSON.toString())));
|
||||
}
|
||||
|
||||
@Test // DATAREST-293
|
||||
public void redirectsToBrowserForApiRootAndHtml() throws Exception {
|
||||
|
||||
mvc.perform(get(BASE_PATH).accept(MediaType.TEXT_HTML)).//
|
||||
andExpect(status().isFound()).//
|
||||
andExpect(header().string(HttpHeaders.LOCATION, endsWith(TARGET)));
|
||||
}
|
||||
|
||||
@Test // DATAREST-293
|
||||
public void forwardsBrowserToIndexHtml() throws Exception {
|
||||
|
||||
mvc.perform(get(BASE_PATH.concat("/browser"))).//
|
||||
andExpect(status().isFound()).//
|
||||
andExpect(header().string(HttpHeaders.LOCATION, endsWith(TARGET)));
|
||||
}
|
||||
|
||||
@Test // DATAREST-293
|
||||
public void exposesHalBrowser() throws Exception {
|
||||
|
||||
mvc.perform(get(BASE_PATH.concat("/browser/index.html"))).//
|
||||
andExpect(status().isOk()).//
|
||||
andExpect(content().string(containsString("The HAL Browser")));
|
||||
}
|
||||
|
||||
@Test // DATAREST-293
|
||||
public void retrunsApiIfHtmlIsNotExplicitlyListed() throws Exception {
|
||||
|
||||
mvc.perform(get(BASE_PATH).accept(MediaType.APPLICATION_JSON, MediaType.ALL)).//
|
||||
andExpect(status().isOk()).//
|
||||
andExpect(header().string(HttpHeaders.CONTENT_TYPE, startsWith(MediaType.APPLICATION_JSON_VALUE)));
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-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.data.rest.webmvc.halbrowser;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.web.filter.ForwardedHeaderFilter;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.view.AbstractView;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link HalBrowser}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @soundtrack Nils Wülker - Homeless Diamond (feat. Lauren Flynn)
|
||||
*/
|
||||
public class HalBrowserUnitTests {
|
||||
|
||||
@Test // DATAREST-565, DATAREST-720
|
||||
public void createsContextRelativeRedirectForBrowser() throws Exception {
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/context");
|
||||
request.setContextPath("/context");
|
||||
|
||||
View view = new HalBrowser().browser(request);
|
||||
|
||||
assertThat(view).isInstanceOf(RedirectView.class);
|
||||
|
||||
((AbstractView) view).render(Collections.<String, Object> emptyMap(), request, response);
|
||||
|
||||
UriComponents components = UriComponentsBuilder.fromUriString(response.getHeader(HttpHeaders.LOCATION)).build();
|
||||
|
||||
assertThat(components.getPath()).startsWith("/context");
|
||||
assertThat(components.getFragment()).isEqualTo("/context");
|
||||
}
|
||||
|
||||
@Test // DATAREST-1264
|
||||
public void producesProxyRelativeRedirectIfNecessary() throws ServletException, IOException {
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/browser");
|
||||
request.addHeader("X-Forwarded-Host", "somehost");
|
||||
request.addHeader("X-Forwarded-Port", "4711");
|
||||
request.addHeader("X-Forwarded-Proto", "https");
|
||||
request.addHeader("X-Forwarded-Prefix", "/prefix");
|
||||
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
|
||||
|
||||
filter.doFilter(request, response, (req, resp) -> {
|
||||
View view = new HalBrowser().browser((HttpServletRequest) req);
|
||||
|
||||
assertThat(view).isInstanceOf(RedirectView.class);
|
||||
|
||||
String url = ((RedirectView) view).getUrl();
|
||||
|
||||
assertThat(url).startsWith("https://somehost:4711/prefix").endsWith("/prefix");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework" level="warn" />
|
||||
|
||||
<root level="warn">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user