Permalink
Browse files

Add possibility to serve static resources like html, css or js.

  • Loading branch information...
ybonnel committed Feb 26, 2013
1 parent b7921de commit 58f93c954a070eab0d716fb45fe20232eab2008e
View
@@ -366,3 +366,29 @@ public class FilterExampleAttributes {
}
```
+
+
+---------------------------------
+
+Example showing how to serve static resources
+
+```java
+import static spark.Spark.*;
+import spark.*;
+
+public class StaticResources {
+
+ public static void main(String[] args) {
+
+ // Will serve all static file are under "/public" in classpath if the route isn't consumed by others routes.
+ staticFileRoute("/public");
+
+ get(new Route("/hello") {
+ @Override
+ public Object handle(Request request, Response response) {
+ return "Hello World!";
+ }
+ });
+ }
+}
+```
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011- Per Wendel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spark;
+
+/**
+ * Exception used for stopping the execution
+ *
+ * @author Yan Bonnel
+ */
+public class NotConsumedException extends RuntimeException {
+}
@@ -54,6 +54,7 @@
private static RouteMatcher routeMatcher;
private static String ipAddress = "0.0.0.0";
private static int port = 4567;
+ private static String staticFileRoute = null;
/**
* Set the IP address that Spark should listen on. If not called the default address is '0.0.0.0'.
@@ -81,6 +82,18 @@ public synchronized static void setPort(int port) {
Spark.port = port;
}
+ /**
+ * Assign a route in classpath for static file.
+ * <b>Careful : this method must be called before all others method.</b>
+ * @param route the route in classpath.
+ */
+ public static void staticFileRoute(String route) {
+ if (initialized) {
+ throw new IllegalStateException("This must be done before route mapping has begun");
+ }
+ staticFileRoute = route;
+ }
+
/**
* Map the route for HTTP GET requests
*
@@ -207,8 +220,8 @@ private synchronized static final void init() {
new Thread(new Runnable() {
@Override
public void run() {
- server = SparkServerFactory.create();
- server.ignite(ipAddress, port);
+ server = SparkServerFactory.create(staticFileRoute != null);
+ server.ignite(ipAddress, port, staticFileRoute);
}
}).start();
initialized = true;
@@ -59,7 +59,7 @@ public void init(FilterConfig filterConfig) throws ServletException {
application.init();
filterPath = FilterTools.getFilterPath(filterConfig);
- matcherFilter = new MatcherFilter(RouteMatcherFactory.get(), true);
+ matcherFilter = new MatcherFilter(RouteMatcherFactory.get(), true, false);
}
/**
@@ -26,6 +26,7 @@
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.log.Log;
+import spark.NotConsumedException;
/**
* Simple Jetty Handler
@@ -44,8 +45,13 @@ public JettyHandler(Filter filter) {
public void doHandle(String target, Request baseRequest, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
Log.debug("jettyhandler, handle();");
- filter.doFilter(request, response, null);
- baseRequest.setHandled(true);
+ try {
+ filter.doFilter(request, response, null);
+ baseRequest.setHandled(true);
+ } catch (NotConsumedException ignore){
+ // TODO : Not use an exception in order to be faster.
+ baseRequest.setHandled(false);
+ }
}
}
@@ -28,12 +28,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import spark.Access;
-import spark.HaltException;
-import spark.Request;
-import spark.RequestResponseFactory;
-import spark.Response;
-import spark.Route;
+import spark.*;
import spark.route.HttpMethod;
import spark.route.RouteMatch;
import spark.route.RouteMatcher;
@@ -47,6 +42,7 @@
private RouteMatcher routeMatcher;
private boolean isServletContext;
+ private boolean haveOthersHandlers;
/** The logger. */
private org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(getClass());
@@ -56,10 +52,12 @@
*
* @param routeMatcher The route matcher
* @param isServletContext If true, chain.doFilter will be invoked if request is not consumed by Spark.
+ * @param haveOthersHandlers If true, do nothing if request is not consumed by Spark in order to let others handlers process the request.
*/
- public MatcherFilter(RouteMatcher routeMatcher, boolean isServletContext) {
+ public MatcherFilter(RouteMatcher routeMatcher, boolean isServletContext, boolean haveOthersHandlers) {
this.routeMatcher = routeMatcher;
this.isServletContext = isServletContext;
+ this.haveOthersHandlers = haveOthersHandlers;
}
public void init(FilterConfig filterConfig) {
@@ -179,8 +177,12 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
}
}
- boolean consumed = bodyContent != null ? true : false;
-
+ boolean consumed = bodyContent != null;
+
+ if (!consumed && haveOthersHandlers) {
+ throw new NotConsumedException();
+ }
+
if (!consumed && !isServletContext) {
httpResponse.setStatus(404);
bodyContent = NOT_FOUND;
@@ -50,6 +50,15 @@
*/
void ignite(String host, int port);
+ /**
+ * Ignites the spark server listening on the provided address and port and serve static files.
+ *
+ * @param host The address to listen on
+ * @param port The port to listen on
+ * @param staticFileRoute the route to static files in classPath
+ */
+ void ignite(String host, int port, String staticFileRoute);
+
/**
* Stops the spark server
*/
@@ -25,8 +25,8 @@
*/
public class SparkServerFactory {
- public static SparkServer create() {
- MatcherFilter matcherFilter = new MatcherFilter(RouteMatcherFactory.get(), false);
+ public static SparkServer create(boolean haveMultipleHandler) {
+ MatcherFilter matcherFilter = new MatcherFilter(RouteMatcherFactory.get(), false, haveMultipleHandler);
matcherFilter.init(null);
JettyHandler handler = new JettyHandler(matcherFilter);
return new SparkServerImpl(handler);
@@ -20,6 +20,9 @@
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.server.handler.ResourceHandler;
+import org.eclipse.jetty.util.resource.Resource;
/**
* Spark server implementation
@@ -57,6 +60,11 @@ public void ignite(String host) {
@Override
public void ignite(String host, int port) {
+ ignite(host, port, null);
+ }
+
+ @Override
+ public void ignite(String host, int port, String staticFilesRoute) {
SocketConnector connector = new SocketConnector();
// Set some timeout options to make debugging easier.
@@ -66,7 +74,17 @@ public void ignite(String host, int port) {
connector.setPort(port);
server.setConnectors(new Connector[] {connector});
- server.setHandler(handler);
+ if (staticFilesRoute == null) {
+ server.setHandler(handler);
+ } else {
+ ResourceHandler resourceHandler = new ResourceHandler();
+ Resource staticResources = Resource.newClassPathResource(staticFilesRoute);
+ resourceHandler.setBaseResource(staticResources);
+ resourceHandler.setWelcomeFiles(new String[]{"index.html"});
+ HandlerList handlers = new HandlerList();
+ handlers.setHandlers(new Handler[]{handler, resourceHandler});
+ server.setHandler(handlers);
+ }
try {
System.out.println("== " + NAME + " has ignited ...");
@@ -1,10 +1,5 @@
package spark;
-import static spark.Spark.after;
-import static spark.Spark.before;
-import static spark.Spark.get;
-import static spark.Spark.post;
-
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -17,6 +12,8 @@
import spark.util.SparkTestUtil;
import spark.util.SparkTestUtil.UrlResponse;
+import static spark.Spark.*;
+
public class GenericIntegrationTest {
static SparkTestUtil testUtil;
@@ -30,6 +27,8 @@ public static void tearDown() {
@BeforeClass
public static void setup() {
testUtil = new SparkTestUtil(4567);
+
+ staticFileRoute("/public");
before(new Filter("/protected/*") {
@@ -47,7 +46,7 @@ public Object handle(Request request, Response response) {
}
});
- get(new Route("/:param") {
+ get(new Route("/param/:param") {
@Override
public Object handle(Request request, Response response) {
@@ -139,7 +138,7 @@ public void testGetRoot() {
@Test
public void testEchoParam1() {
try {
- UrlResponse response = testUtil.doMethod("GET", "/shizzy", null);
+ UrlResponse response = testUtil.doMethod("GET", "/param/shizzy", null);
Assert.assertEquals(200, response.status);
Assert.assertEquals("echo: shizzy", response.body);
} catch (Throwable e) {
@@ -150,7 +149,7 @@ public void testEchoParam1() {
@Test
public void testEchoParam2() {
try {
- UrlResponse response = testUtil.doMethod("GET", "/gunit", null);
+ UrlResponse response = testUtil.doMethod("GET", "/param/gunit", null);
Assert.assertEquals(200, response.status);
Assert.assertEquals("echo: gunit", response.body);
} catch (Throwable e) {
@@ -200,4 +199,11 @@ public void testPost() {
}
}
+ @Test
+ public void testStaticFile() throws Exception {
+ UrlResponse response = testUtil.doMethod("GET", "/static.html", null);
+ Assert.assertEquals(200, response.status);
+ Assert.assertEquals("Content of html file", response.body);
+ }
+
}
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011- Per Wendel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package spark.examples.staticresources;
+
+import spark.Request;
+import spark.Response;
+import spark.Route;
+
+import static spark.Spark.get;
+import static spark.Spark.staticFileRoute;
+
+/**
+ * Example showing how serve static resources.
+ */
+public class StaticResources {
+
+ public static void main(String[] args) {
+
+ // Will serve all static file are under "/public" in classpath if the route isn't consumed by others routes.
+ staticFileRoute("/public");
+
+ get(new Route("/hello") {
+ @Override
+ public Object handle(Request request, Response response) {
+ return "Hello World!";
+ }
+ });
+ }
+}
@@ -0,0 +1 @@
+Content of html file

0 comments on commit 58f93c9

Please sign in to comment.