Commit af1278a4 by Dave Syer

Ensure static resources load from relative paths

Most browsers support <base href="..."> these days and there was one already in statut.ftl (but not in navbar). Added a test that asserts the css is loadable as well. Fixes gh-55
parent e2e193ea
...@@ -6,16 +6,17 @@ import com.netflix.appinfo.DataCenterInfo; ...@@ -6,16 +6,17 @@ import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo;
import com.netflix.config.ConfigurationManager; import com.netflix.config.ConfigurationManager;
import com.netflix.discovery.shared.*; import com.netflix.discovery.shared.*;
import com.netflix.discovery.shared.Application;
import com.netflix.eureka.PeerAwareInstanceRegistry; import com.netflix.eureka.PeerAwareInstanceRegistry;
import com.netflix.eureka.cluster.PeerEurekaNode; import com.netflix.eureka.cluster.PeerEurekaNode;
import com.netflix.eureka.resources.StatusResource; import com.netflix.eureka.resources.StatusResource;
import com.netflix.eureka.util.StatusInfo; import com.netflix.eureka.util.StatusInfo;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.net.URI; import java.net.URI;
import java.util.*; import java.util.*;
...@@ -69,7 +70,8 @@ public class EurekaController { ...@@ -69,7 +70,8 @@ public class EurekaController {
} }
private void populateBase(HttpServletRequest request, Map<String, Object> model) { private void populateBase(HttpServletRequest request, Map<String, Object> model) {
String path = request.getContextPath(); String servletPath = request.getServletPath();
String path = request.getContextPath() + (servletPath==null ? "" : servletPath);
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
model.put("time", new Date()); model.put("time", new Date());
...@@ -104,7 +106,7 @@ public class EurekaController { ...@@ -104,7 +106,7 @@ public class EurekaController {
for (PeerEurekaNode node : list) { for (PeerEurekaNode node : list) {
try { try {
URI uri = new URI(node.getServiceUrl()); URI uri = new URI(node.getServiceUrl());
String href = "http://" + uri.getHost() + ":" + uri.getPort() + request.getContextPath(); String href = node.getServiceUrl();
replicas.put(uri.getHost(), href); replicas.put(uri.getHost(), href);
} catch(Exception e) { } catch(Exception e) {
//ignore? //ignore?
......
<nav class="navbar navbar-default" role="navigation"> <nav class="navbar navbar-default" role="navigation">
<div class="container"> <div class="container">
<div class="navbar-header"> <div class="navbar-header">
<a class="navbar-brand" href="/"><span></span></a> <a class="navbar-brand" href="${basePath}"><span></span></a>
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span> <span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li> <li>
<a href="/">Home</a> <a href="${basePath}">Home</a>
</li> </li>
<li> <li>
<a href="lastn">Last 1000 since startup</a> <a href="lastn">Last 1000 since startup</a>
......
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]--> <!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]--> <!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head> <head>
<base href="${basePath}">
<title>Eureka - Last N events</title> <title>Eureka - Last N events</title>
<link rel="stylesheet" type="text/css" href="/eureka/css/wro.css"> <link rel="stylesheet" type="text/css" href="eureka/css/wro.css">
</head> </head>
<body id="three"> <body id="three">
...@@ -59,8 +60,8 @@ ...@@ -59,8 +60,8 @@
</div> </div>
</div> </div>
</div> </div>
<script type="text/javascript" src="/webjars/jquery/2.1.1jquery-min.js" ></script> <script type="text/javascript" src="webjars/jquery/2.1.1/jquery.min.js" ></script>
<script type="text/javascript" src="/webjars/bootstrap/3.2.0/js/bootstrap.min.js" ></script> <script type="text/javascript" src="webjars/bootstrap/3.2.0/js/bootstrap.min.js" ></script>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
$('#myTab a:last').tab('show') $('#myTab a:last').tab('show')
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<meta name="description" content=""> <meta name="description" content="">
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="/eureka/css/wro.css"> <link rel="stylesheet" href="eureka/css/wro.css">
</head> </head>
...@@ -101,8 +101,8 @@ ...@@ -101,8 +101,8 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<script type="text/javascript" src="/webjars/jquery/2.1.1/jquery.min.js" ></script> <script type="text/javascript" src="webjars/jquery/2.1.1/jquery.min.js" ></script>
<script type="text/javascript" src="/webjars/bootstrap/3.2.0/js/bootstrap.min.js" ></script> <script type="text/javascript" src="webjars/bootstrap/3.2.0/js/bootstrap.min.js" ></script>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
$('table.stripeable tr:odd').addClass('odd'); $('table.stripeable tr:odd').addClass('odd');
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
} }
.navbar a.navbar-brand { .navbar a.navbar-brand {
background: url("images/spring-logo-xd.png") -1px -1px no-repeat; background: url("../images/spring-logo-xd.png") -1px -1px no-repeat;
margin: 12px 0 6px; margin: 12px 0 6px;
width: 229px; width: 229px;
height: 46px; height: 46px;
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
display: block; display: block;
width: 229px; width: 229px;
height: 46px; height: 46px;
background: url("images/spring-logo-xd.png") -1px -48px no-repeat; background: url("../images/spring-logo-xd.png") -1px -48px no-repeat;
opacity: 0; opacity: 0;
-moz-transition: opacity 0.12s ease-in-out; -moz-transition: opacity 0.12s ease-in-out;
-webkit-transition: opacity 0.12s ease-in-out; -webkit-transition: opacity 0.12s ease-in-out;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
width: 148px; width: 148px;
height: 50px; height: 50px;
float: none; float: none;
background: url("images/spring-logo-xd-mobile.png") 0 center no-repeat; background: url("../images/spring-logo-xd-mobile.png") 0 center no-repeat;
} }
.homepage-billboard .homepage-subtitle { .homepage-billboard .homepage-subtitle {
......
@font-face { @font-face {
font-family: 'varela_roundregular'; font-family: 'varela_roundregular';
src: url('fonts/varela_round-webfont.eot'); src: url('../fonts/varela_round-webfont.eot');
src: url('fonts/varela_round-webfont.eot?#iefix') format('embedded-opentype'), src: url('../fonts/varela_round-webfont.eot?#iefix') format('embedded-opentype'),
url('fonts/varela_round-webfont.woff') format('woff'), url('../fonts/varela_round-webfont.woff') format('woff'),
url('fonts/varela_round-webfont.ttf') format('truetype'), url('../fonts/varela_round-webfont.ttf') format('truetype'),
url('fonts/varela_round-webfont.svg#varela_roundregular') format('svg'); url('../fonts/varela_round-webfont.svg#varela_roundregular') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'montserratregular'; font-family: 'montserratregular';
src: url('fonts/montserrat-webfont.eot'); src: url('../fonts/montserrat-webfont.eot');
src: url('fonts/montserrat-webfont.eot?#iefix') format('embedded-opentype'), src: url('../fonts/montserrat-webfont.eot?#iefix') format('embedded-opentype'),
url('fonts/montserrat-webfont.woff') format('woff'), url('../fonts/montserrat-webfont.woff') format('woff'),
url('fonts/montserrat-webfont.ttf') format('truetype'), url('../fonts/montserrat-webfont.ttf') format('truetype'),
url('fonts/montserrat-webfont.svg#montserratregular') format('svg'); url('../fonts/montserrat-webfont.svg#montserratregular') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
......
package org.springframework.cloud.netflix.eureka.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.cloud.netflix.eureka.server.ApplicationContextTests.Application;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest({ "server.port=0", "spring.application.name=eureka",
"server.contextPath=/context" })
public class ApplicationContextTests {
@Value("${local.server.port}")
private int port = 0;
@Configuration
@EnableAutoConfiguration
@EnableEurekaServer
protected static class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=eureka", "server.contextPath=/context").run(
args);
}
}
@Test
public void catalogLoads() {
@SuppressWarnings("rawtypes")
ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(
"http://localhost:" + port + "/context/eureka/apps", Map.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
}
@Test
public void dashboardLoads() {
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
"http://localhost:" + port + "/context/", String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
String body = entity.getBody();
// System.err.println(body);
assertTrue(body.contains("webjars/"));
assertTrue(body.contains("eureka/css"));
// The "DS Replicas"
assertTrue(body.contains("<a href=\"http://localhost:8761/eureka/\">localhost</a>"));
}
@Test
public void cssAvailable() {
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
"http://localhost:" + port + "/context/eureka/css/wro.css", String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
}
@Test
public void adminLoads() {
@SuppressWarnings("rawtypes")
ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(
"http://localhost:" + port + "/context/env", Map.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
}
}
package org.springframework.cloud.netflix.eureka.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.cloud.netflix.eureka.server.ApplicationServletPathTests.Application;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest({ "server.port=0", "spring.application.name=eureka",
"server.servletPath=/servlet" })
public class ApplicationServletPathTests {
@Value("${local.server.port}")
private int port = 0;
@Configuration
@EnableAutoConfiguration
@EnableEurekaServer
protected static class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=eureka", "server.servletPath=/servlet").run(
args);
}
}
@Test
public void catalogLoads() {
@SuppressWarnings("rawtypes")
ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(
"http://localhost:" + port + "/eureka/apps", Map.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
}
@Test
public void dashboardLoads() {
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
"http://localhost:" + port + "/servlet/", String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
String body = entity.getBody();
// System.err.println(body);
assertTrue(body.contains("webjars/"));
assertTrue(body.contains("eureka/css"));
// The "DS Replicas"
assertTrue(body.contains("<a href=\"http://localhost:8761/eureka/\">localhost</a>"));
}
@Test
public void cssAvailable() {
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
"http://localhost:" + port + "/servlet/eureka/css/wro.css", String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
}
@Test
public void adminLoads() {
@SuppressWarnings("rawtypes")
ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(
"http://localhost:" + port + "/servlet/env", Map.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
}
}
...@@ -22,7 +22,7 @@ import org.springframework.test.context.web.WebAppConfiguration; ...@@ -22,7 +22,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class) @SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration @WebAppConfiguration
@IntegrationTest({ "server.port=0", "spring.application.name=eureka", "spring.jmx.enabled=true" }) @IntegrationTest({ "server.port=0", "spring.jmx.enabled=true" })
public class ApplicationTests { public class ApplicationTests {
@Value("${local.server.port}") @Value("${local.server.port}")
...@@ -34,8 +34,7 @@ public class ApplicationTests { ...@@ -34,8 +34,7 @@ public class ApplicationTests {
protected static class Application { protected static class Application {
public static void main(String[] args) { public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties( new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=eureka", "management.contextPath=/admin") "spring.application.name=eureka").run(args);
.run(args);
} }
} }
......
spring.application.name=eureka
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=false
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment