http-service: switch to spring-web from sparkjava/guice

This commit is contained in:
Adam
2017-08-10 17:56:03 -04:00
parent a81935849d
commit b6a7108ca5
18 changed files with 339 additions and 801 deletions

View File

@@ -36,60 +36,39 @@
<packaging>war</packaging>
<properties>
<jetty.version>9.3.6.v20151106</jetty.version> <!-- from Spark -->
<spring.boot.version>1.5.6.RELEASE</spring.boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>${spring.boot.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>${spring.boot.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>net.runelite</groupId>
<artifactId>http-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.5.5</version>
<exclusions>
<!-- Spark includes Jetty, even if you are using
another servlet container, so we exclude it -->
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-servlet</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.sql2o</groupId>
<artifactId>sql2o</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
@@ -100,30 +79,23 @@
<artifactId>guava</artifactId>
<version>21.0</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>com.commongroundpublishing</groupId>
<artifactId>slf4j-servletcontext</artifactId>
<version>1.0.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.scribejava</groupId>
<artifactId>scribejava-apis</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@@ -136,43 +108,10 @@
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<!-- Spark tests use Jetty though, so include it here -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-servlet</artifactId>
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-testlib</artifactId>
<version>4.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.12</version>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.43</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -187,6 +126,11 @@
<finalName>runelite-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>

View File

@@ -1,155 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.http.service;
import com.google.inject.Guice;
import com.google.inject.Inject;
import net.runelite.http.api.RuneliteAPI;
import net.runelite.http.service.account.AccountService;
import net.runelite.http.service.account.AuthFilter;
import net.runelite.http.service.config.ConfigService;
import net.runelite.http.service.examine.ExamineService;
import net.runelite.http.service.hiscore.HiscoreService;
import net.runelite.http.service.item.ItemService;
import net.runelite.http.service.updatecheck.UpdateCheckService;
import net.runelite.http.service.worlds.WorldsService;
import net.runelite.http.service.xtea.XteaService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import spark.Request;
import spark.Response;
import spark.servlet.SparkApplication;
import static spark.Spark.*;
public class Service implements SparkApplication
{
private static final Logger logger = LoggerFactory.getLogger(Service.class);
private final JsonTransformer transformer = new JsonTransformer();
@Inject
private AuthFilter authFilter;
@Inject
private AccountService accounts;
@Inject
private ConfigService config;
@Inject
private ExamineService examine;
@Inject
private HiscoreService hiscores;
@Inject
private ItemService item;
@Inject
private UpdateCheckService updateCheck;
@Inject
private WorldsService worlds;
@Inject
private XteaService xtea;
@Override
public void init()
{
Guice.createInjector(new ServiceModule(this));
setupRoutes();
}
public void setupRoutes()
{
xtea.init();
accounts.init();
config.init();
item.init();
examine.init();
get("/version", (request, response) -> RuneliteAPI.getVersion());
get("/update-check", updateCheck::check, transformer);
path("/hiscore", () ->
{
get("", hiscores::lookup, transformer);
get("/:skill", hiscores::singleSkillLookup, transformer);
});
get("/worlds", worlds::listWorlds, transformer);
post("/xtea", xtea::submit);
get("/xtea/:rev", xtea::get, transformer);
path("/account", () ->
{
get("/login", accounts::login, transformer);
get("/callback", accounts::callback);
before("/logout", authFilter);
get("/logout", accounts::logout);
before("/session-check", authFilter);
get("/session-check", accounts::sessionCheck);
});
before("/config", authFilter);
path("/config", () ->
{
// Just using before(authFilter); here doesn't work
before("/*", authFilter);
get("", config::get, transformer);
put("/:key", config::setKey);
delete("/:key", config::unsetKey);
});
path("/item", () ->
{
get("/search", item::search, transformer);
get("/:id", item::getItem, transformer);
get("/:id/icon", item::getIcon);
get("/:id/icon/large", item::getIconLarge);
get("/:id/price", item::getPrice, transformer);
get("/:id/price/:time", item::getPrice, transformer);
});
path("/examine", () ->
{
get("/npc/:id", examine::getNpc);
get("/object/:id", examine::getObject);
get("/item/:id", examine::getItem);
post("/npc/:id", examine::submitNpc);
post("/object/:id", examine::submitObject);
post("/item/:id", examine::submitItem);
});
exception(Exception.class, this::handleException);
}
private void handleException(Exception ex, Request request, Response response)
{
logger.warn("error processing request", ex);
response.status(500);
}
}

View File

@@ -1,111 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.http.service;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import spark.globalstate.ServletFlag;
import spark.http.matching.MatcherFilter;
import spark.route.ServletRoutes;
import spark.servlet.SparkApplication;
import spark.staticfiles.StaticFilesConfiguration;
public class SparkServlet extends HttpServlet
{
private final SparkApplication service = new Service();
private final MatcherFilter matcherFilter;
public SparkServlet()
{
ServletFlag.runFromServlet();
service.init();
matcherFilter = new MatcherFilter(ServletRoutes.get(), StaticFilesConfiguration.servletInstance, true, false);
}
private void run(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
final String relativePath = req.getPathInfo();
HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(req)
{
@Override
public String getPathInfo()
{
return relativePath;
}
@Override
public String getRequestURI()
{
return relativePath;
}
};
FilterChain chain = (req2, resp2) ->
{
// Called if the matcherFilter ends up not setting a body
// something might have changed changed the error from 200
if (resp.getStatus() == 200)
{
resp.setStatus(404);
}
};
matcherFilter.doFilter(requestWrapper, resp, chain);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
run(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
run(req, resp);
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
run(req, resp);
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
run(req, resp);
}
}

View File

@@ -24,9 +24,6 @@
*/
package net.runelite.http.service;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.name.Named;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
@@ -34,99 +31,54 @@ import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import net.runelite.http.service.account.AccountService;
import net.runelite.http.service.account.AuthFilter;
import net.runelite.http.service.config.ConfigService;
import net.runelite.http.service.examine.ExamineService;
import net.runelite.http.service.hiscore.HiscoreService;
import net.runelite.http.service.item.ItemService;
import net.runelite.http.service.updatecheck.UpdateCheckService;
import net.runelite.http.service.worlds.WorldsService;
import net.runelite.http.service.xtea.XteaService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.sql2o.Sql2o;
import org.sql2o.converters.Converter;
import org.sql2o.quirks.NoQuirks;
public class ServiceModule extends AbstractModule
@SpringBootApplication
public class SpringBootWebApplication extends SpringBootServletInitializer
{
private final Service service;
public ServiceModule(Service service)
{
this.service = service;
}
private Context getContext() throws NamingException
{
Context initCtx = new InitialContext();
return (Context) initCtx.lookup("java:comp/env");
}
@Provides
@Named("Runelite JDBC")
DataSource provideDataSource()
{
try
{
return (DataSource) getContext().lookup("jdbc/runelite");
}
catch (NamingException ex)
{
throw new RuntimeException(ex);
}
}
@Provides
@Named("Runelite SQL2O")
Sql2o provideSql2o(@Named("Runelite JDBC") DataSource datasource)
@Bean("Runelite SQL2O")
Sql2o sql2o() throws NamingException
{
DataSource dataSource = (DataSource) getContext().lookup("jdbc/runelite");
Map<Class, Converter> converters = new HashMap<>();
converters.put(Instant.class, new InstantConverter());
return new Sql2o(datasource, new NoQuirks(converters));
return new Sql2o(dataSource, new NoQuirks(converters));
}
@Provides
@Named("OAuth Client ID")
String provideOAuthClientID()
@Bean("OAuth Client ID")
String oauthClientId() throws NamingException
{
try
{
return (String) getContext().lookup("runelite-oauth-client-id");
}
catch (NamingException ex)
{
throw new RuntimeException(ex);
}
return (String) getContext().lookup("runelite-oauth-client-id");
}
@Provides
@Named("OAuth Client Secret")
String provideOAuthClientSecret()
@Bean("OAuth Client Secret")
String oauthClientSecret() throws NamingException
{
try
{
return (String) getContext().lookup("runelite-oauth-client-secret");
}
catch (NamingException ex)
{
throw new RuntimeException(ex);
}
return (String) getContext().lookup("runelite-oauth-client-secret");
}
@Override
protected void configure()
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
bind(Service.class).toInstance(service);
return application.sources(SpringBootWebApplication.class);
}
bind(AuthFilter.class);
bind(AccountService.class);
bind(ConfigService.class);
bind(ExamineService.class);
bind(HiscoreService.class);
bind(ItemService.class);
bind(UpdateCheckService.class);
bind(WorldsService.class);
bind(XteaService.class);
public static void main(String[] args)
{
SpringApplication.run(SpringBootWebApplication.class, args);
}
}

View File

@@ -30,14 +30,15 @@ import com.github.scribejava.apis.GoogleApi20;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.github.scribejava.core.model.OAuthRequest;
import com.github.scribejava.core.model.Response;
import com.github.scribejava.core.model.Verb;
import com.github.scribejava.core.oauth.OAuth20Service;
import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.runelite.http.api.RuneliteAPI;
import net.runelite.http.api.account.OAuthResponse;
import net.runelite.http.api.ws.messages.LoginResponse;
@@ -46,12 +47,17 @@ import net.runelite.http.service.ws.WSService;
import net.runelite.http.service.ws.WSSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.sql2o.Connection;
import org.sql2o.Sql2o;
import org.sql2o.Sql2oException;
import spark.Request;
import spark.Response;
@RestController
@RequestMapping("/account")
public class AccountService
{
private static final Logger logger = LoggerFactory.getLogger(AccountService.class);
@@ -86,21 +92,21 @@ public class AccountService
private final Sql2o sql2o;
private final String oauthClientId;
private final String oauthClientSecret;
private final AuthFilter auth;
@Inject
@Autowired
public AccountService(
@Named("Runelite SQL2O") Sql2o sql2o,
@Named("OAuth Client ID") String oauthClientId,
@Named("OAuth Client Secret") String oauthClientSecret
@Qualifier("Runelite SQL2O") Sql2o sql2o,
@Qualifier("OAuth Client ID") String oauthClientId,
@Qualifier("OAuth Client Secret") String oauthClientSecret,
AuthFilter auth
)
{
this.sql2o = sql2o;
this.oauthClientId = oauthClientId;
this.oauthClientSecret = oauthClientSecret;
}
this.auth = auth;
public void init()
{
try (Connection con = sql2o.open())
{
con.createQuery(CREATE_SESSIONS)
@@ -121,7 +127,8 @@ public class AccountService
}
}
public OAuthResponse login(Request request, Response response)
@RequestMapping("/login")
public OAuthResponse login()
{
UUID uuid = UUID.randomUUID();
@@ -143,24 +150,25 @@ public class AccountService
lr.setOauthUrl(authorizationUrl);
lr.setUid(uuid);
response.type("application/json");
return lr;
}
public Object callback(Request request, Response response) throws IOException, InterruptedException, ExecutionException
@RequestMapping("/callback")
public Object callback(
HttpServletRequest request,
HttpServletResponse response,
@RequestParam String error,
@RequestParam String code,
@RequestParam State state
) throws InterruptedException, ExecutionException, IOException
{
String error = request.queryParams("error");
if (error != null)
{
logger.info("Error in oauth callback: {}", error);
return null;
}
String authorizationCode = request.queryParams("code");
State state = gson.fromJson(request.queryParams("state"), State.class);
logger.info("Got authorization code {} for uuid {}", authorizationCode, state.getUuid());
logger.info("Got authorization code {} for uuid {}", code, state.getUuid());
OAuth20Service service = new ServiceBuilder()
.apiKey(oauthClientId)
@@ -170,13 +178,13 @@ public class AccountService
.state(gson.toJson(state))
.build(GoogleApi20.instance());
OAuth2AccessToken accessToken = service.getAccessToken(authorizationCode);
OAuth2AccessToken accessToken = service.getAccessToken(code);
// Access user info
OAuthRequest orequest = new OAuthRequest(Verb.GET, USERINFO);
service.signRequest(accessToken, orequest);
com.github.scribejava.core.model.Response oresponse = service.execute(orequest);
Response oresponse = service.execute(orequest);
if (oresponse.getCode() / 100 != 2)
{
@@ -213,7 +221,7 @@ public class AccountService
logger.info("Created session for user {}", userInfo.getEmail());
}
response.redirect(RL_REDIR);
response.sendRedirect(RL_REDIR);
notifySession(state.getUuid(), userInfo.getEmail());
@@ -237,9 +245,15 @@ public class AccountService
service.send(response);
}
public Object logout(Request request, Response response)
@RequestMapping("/logout")
public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException
{
SessionEntry session = request.session().attribute("session");
SessionEntry session = auth.handle(request, response);
if (session == null)
{
return;
}
try (Connection con = sql2o.open())
{
@@ -247,13 +261,11 @@ public class AccountService
.addParameter("uuid", session.getUuid().toString())
.executeUpdate();
}
return "";
}
public Object sessionCheck(Request request, Response response)
@RequestMapping("/session-check")
public void sessionCheck(HttpServletRequest request, HttpServletResponse response) throws IOException
{
// Auth filter would kick this out before here
return "";
auth.handle(request, response);
}
}

View File

@@ -24,39 +24,38 @@
*/
package net.runelite.http.service.account;
import java.io.IOException;
import net.runelite.http.service.account.beans.SessionEntry;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.runelite.http.api.RuneliteAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.sql2o.Connection;
import org.sql2o.Sql2o;
import spark.Filter;
import spark.Request;
import spark.Response;
import spark.Session;
import static spark.Spark.halt;
public class AuthFilter implements Filter
@Service
public class AuthFilter
{
private final Sql2o sql2o;
@Inject
public AuthFilter(@Named("Runelite SQL2O") Sql2o sql2o)
@Autowired
public AuthFilter(@Qualifier("Runelite SQL2O") Sql2o sql2o)
{
this.sql2o = sql2o;
}
@Override
public void handle(Request request, Response response) throws Exception
public SessionEntry handle(HttpServletRequest request, HttpServletResponse response) throws IOException
{
String runeliteAuth = request.headers(RuneliteAPI.RUNELITE_AUTH);
String runeliteAuth = request.getHeader(RuneliteAPI.RUNELITE_AUTH);
if (runeliteAuth == null)
{
halt(401, "Access denied");
return;
response.sendError(401, "Access denied");
return null;
}
UUID uuid = UUID.fromString(runeliteAuth);
@@ -69,8 +68,8 @@ public class AuthFilter implements Filter
if (sessionEntry == null)
{
halt(401, "Access denied");
return;
response.sendError(401, "Access denied");
return null;
}
Instant now = Instant.now();
@@ -82,8 +81,7 @@ public class AuthFilter implements Filter
sessionEntry.setLastUsed(now);
Session session = request.session();
session.attribute("session", sessionEntry);
return sessionEntry;
}
}

View File

@@ -24,18 +24,28 @@
*/
package net.runelite.http.service.config;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.runelite.http.api.config.ConfigEntry;
import net.runelite.http.api.config.Configuration;
import net.runelite.http.service.account.AuthFilter;
import net.runelite.http.service.account.beans.SessionEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
import org.springframework.web.bind.annotation.RestController;
import org.sql2o.Connection;
import org.sql2o.Sql2o;
import org.sql2o.Sql2oException;
import spark.Request;
import spark.Response;
@RestController
@RequestMapping("/config")
public class ConfigService
{
private static final String CREATE_CONFIG = "CREATE TABLE IF NOT EXISTS `config` (\n"
@@ -49,15 +59,17 @@ public class ConfigService
+ " ADD CONSTRAINT `user_fk` FOREIGN KEY (`user`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;";
private final Sql2o sql2o;
private final AuthFilter auth;
@Inject
public ConfigService(@Named("Runelite SQL2O") Sql2o sql2o)
@Autowired
public ConfigService(
@Qualifier("Runelite SQL2O") Sql2o sql2o,
AuthFilter auth
)
{
this.sql2o = sql2o;
}
this.auth = auth;
public void init()
{
try (Connection con = sql2o.open())
{
con.createQuery(CREATE_CONFIG)
@@ -75,9 +87,15 @@ public class ConfigService
}
}
public Configuration get(Request request, Response response)
@RequestMapping
public Configuration get(HttpServletRequest request, HttpServletResponse response) throws IOException
{
SessionEntry session = request.session().attribute("session");
SessionEntry session = auth.handle(request, response);
if (session == null)
{
return null;
}
List<ConfigEntry> config;
@@ -88,38 +106,54 @@ public class ConfigService
.executeAndFetch(ConfigEntry.class);
}
response.type("application/json");
return new Configuration(config);
}
public Object setKey(Request request, Response response)
@RequestMapping(path = "/{key}", method = PUT)
public void setKey(
HttpServletRequest request,
HttpServletResponse response,
@PathVariable String key,
@RequestBody String value
) throws IOException
{
SessionEntry session = request.session().attribute("session");
SessionEntry session = auth.handle(request, response);
if (session == null)
{
return;
}
try (Connection con = sql2o.open())
{
con.createQuery("insert into config (user, `key`, value) values (:user, :key, :value) on duplicate key update value = :value")
.addParameter("user", session.getUser())
.addParameter("key", request.params("key"))
.addParameter("value", request.body())
.addParameter("key", key)
.addParameter("value", value)
.executeUpdate();
}
return "";
}
public Object unsetKey(Request request, Response response)
@RequestMapping(path = "/{key}", method = DELETE)
public void unsetKey(
HttpServletRequest request,
HttpServletResponse response,
@PathVariable String key
) throws IOException
{
SessionEntry session = request.session().attribute("session");
SessionEntry session = auth.handle(request, response);
if (session == null)
{
return;
}
try (Connection con = sql2o.open())
{
con.createQuery("delete from config where user = :user and `key` = :key")
.addParameter("user", session.getUser())
.addParameter("key", request.params("key"))
.addParameter("key", key)
.executeUpdate();
}
return "";
}
}

View File

@@ -24,8 +24,6 @@
*/
package net.runelite.http.service.examine;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import java.sql.Timestamp;
import java.time.Instant;
import static net.runelite.http.service.examine.ExamineType.ITEM;
@@ -33,11 +31,18 @@ import static net.runelite.http.service.examine.ExamineType.NPC;
import static net.runelite.http.service.examine.ExamineType.OBJECT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import org.springframework.web.bind.annotation.RestController;
import org.sql2o.Connection;
import org.sql2o.Sql2o;
import spark.Request;
import spark.Response;
@RestController
@RequestMapping("/examine")
public class ExamineService
{
private static final Logger logger = LoggerFactory.getLogger(ExamineService.class);
@@ -53,14 +58,11 @@ public class ExamineService
private final Sql2o sql2o;
@Inject
public ExamineService(@Named("Runelite SQL2O") Sql2o sql2o)
@Autowired
public ExamineService(@Qualifier("Runelite SQL2O") Sql2o sql2o)
{
this.sql2o = sql2o;
}
public void init()
{
try (Connection con = sql2o.open())
{
con.createQuery(CREATE_EXAMINE)
@@ -68,49 +70,40 @@ public class ExamineService
}
}
public String getNpc(Request request, Response response)
@RequestMapping("/npc/{id}")
public String getNpc(@PathVariable int id)
{
int id = Integer.parseInt(request.params("id"));
return get(NPC, id);
}
public String getObject(Request request, Response response)
@RequestMapping("/object/{id}")
public String getObject(@PathVariable int id)
{
int id = Integer.parseInt(request.params("id"));
return get(OBJECT, id);
}
public String getItem(Request request, Response response)
@RequestMapping("/item/{id}")
public String getItem(@PathVariable int id)
{
int id = Integer.parseInt(request.params("id"));
return get(ITEM, id);
}
public Object submitNpc(Request request, Response response)
@RequestMapping(path = "/npc/{id}", method = POST)
public void submitNpc(@PathVariable int id, @RequestBody String examine)
{
int id = Integer.parseInt(request.params("id"));
String examine = request.body();
insert(NPC, id, examine);
return "";
}
public Object submitObject(Request request, Response response)
@RequestMapping(path = "/object/{id}", method = POST)
public void submitObject(@PathVariable int id, @RequestBody String examine)
{
int id = Integer.parseInt(request.params("id"));
String examine = request.body();
insert(OBJECT, id, examine);
return "";
}
public Object submitItem(Request request, Response response)
@RequestMapping(path = "/item/{id}", method = POST)
public void submitItem(@PathVariable int id, @RequestBody String examine)
{
int id = Integer.parseInt(request.params("id"));
String examine = request.body();
insert(ITEM, id, examine);
return "";
}
private String get(ExamineType type, int id)

View File

@@ -31,30 +31,42 @@ import net.runelite.http.api.hiscore.SingleHiscoreSkillResult;
import net.runelite.http.api.hiscore.Skill;
import net.runelite.http.api.hiscore.HiscoreSkill;
import okhttp3.HttpUrl;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import spark.Request;
import spark.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hiscore")
public class HiscoreService
{
private static final Logger logger = LoggerFactory.getLogger(HiscoreService.class);
private static final HttpUrl RUNESCAPE_HISCORE_SERVICE = HttpUrl.parse("http://services.runescape.com/m=hiscore_oldschool/index_lite.ws");
private HttpUrl url = RUNESCAPE_HISCORE_SERVICE;
private HiscoreResultBuilder lookup(String username) throws IOException
private HiscoreResultBuilder lookupUsername(String username) throws IOException
{
HttpUrl hiscoreUrl = url.newBuilder()
.addQueryParameter("player", username)
.build();
okhttp3.Request okrequest = new okhttp3.Request.Builder()
logger.info("Built URL {}", hiscoreUrl);
Request okrequest = new Request.Builder()
.url(hiscoreUrl)
.build();
okhttp3.Response okresponse = RuneliteAPI.CLIENT.newCall(okrequest).execute();
Response okresponse = RuneliteAPI.CLIENT.newCall(okrequest).execute();
String responseStr;
try (ResponseBody body = okresponse.body())
@@ -88,24 +100,20 @@ public class HiscoreService
return hiscoreBuilder;
}
public HiscoreResult lookup(Request request, Response response) throws IOException
@RequestMapping
public HiscoreResult lookup(@RequestParam String username) throws IOException
{
String username = request.queryParams("username");
HiscoreResultBuilder result = lookup(username);
response.type("application/json");
HiscoreResultBuilder result = lookupUsername(username);
return result.build();
}
public SingleHiscoreSkillResult singleSkillLookup(Request request, Response response) throws IOException
@RequestMapping("/{skillName}")
public SingleHiscoreSkillResult singleSkillLookup(@PathVariable String skillName, @RequestParam String username) throws IOException
{
String username = request.queryParams("username");
String skillName = request.params("skill");
HiscoreSkill skill = HiscoreSkill.valueOf(skillName.toUpperCase());
// RS api only supports looking up all stats
HiscoreResultBuilder result = lookup(username);
HiscoreResultBuilder result = lookupUsername(username);
// Find the skill to return
Skill requested = result.getSkill(skill.ordinal());
@@ -115,7 +123,6 @@ public class HiscoreService
skillResult.setSkillName(skillName);
skillResult.setSkill(requested);
response.type("application/json");
return skillResult;
}

View File

@@ -27,8 +27,6 @@ package net.runelite.http.service.item;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.gson.JsonParseException;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -38,22 +36,31 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import net.runelite.http.api.RuneliteAPI;
import net.runelite.http.api.item.Item;
import net.runelite.http.api.item.ItemPrice;
import net.runelite.http.api.item.ItemType;
import net.runelite.http.api.item.SearchResult;
import okhttp3.HttpUrl;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.sql2o.Connection;
import org.sql2o.Query;
import org.sql2o.Sql2o;
import org.sql2o.Sql2oException;
import spark.Request;
import spark.Response;
@RestController
@RequestMapping("/item")
public class ItemService
{
private static final Logger logger = LoggerFactory.getLogger(ItemService.class);
@@ -94,14 +101,11 @@ public class ItemService
.maximumSize(1024L)
.build();
@Inject
public ItemService(@Named("Runelite SQL2O") Sql2o sql2o)
@Autowired
public ItemService(@Qualifier("Runelite SQL2O") Sql2o sql2o)
{
this.sql2o = sql2o;
}
public void init()
{
try (Connection con = sql2o.open())
{
con.createQuery(CREATE_ITEMS)
@@ -132,91 +136,79 @@ public class ItemService
}
}
public Item getItem(Request request, Response response)
@RequestMapping("/{itemId}")
public Item getItem(HttpServletResponse response, @PathVariable int itemId)
{
int itemId = Integer.parseInt(request.params("id"));
ItemEntry item = getItem(itemId);
if (item != null)
{
response.type("application/json");
response.header(RUNELITE_CACHE, "HIT");
response.setHeader(RUNELITE_CACHE, "HIT");
return item.toItem();
}
item = fetchItem(itemId);
if (item != null)
{
response.type("application/json");
response.header(RUNELITE_CACHE, "MISS");
response.setHeader(RUNELITE_CACHE, "MISS");
return item.toItem();
}
return null;
}
public byte[] getIcon(Request request, Response response)
@RequestMapping(path = "/{itemId}/icon", produces = "image/gif")
public byte[] getIcon(HttpServletResponse response, @PathVariable int itemId)
{
int itemId = Integer.parseInt(request.params("id"));
ItemEntry item = getItem(itemId);
if (item != null && item.getIcon() != null)
{
response.type("image/gif");
response.header(RUNELITE_CACHE, "HIT");
response.setHeader(RUNELITE_CACHE, "HIT");
return item.getIcon();
}
item = fetchItem(itemId);
if (item != null)
{
response.type("image/gif");
response.header(RUNELITE_CACHE, "MISS");
response.setHeader(RUNELITE_CACHE, "MISS");
return item.getIcon();
}
return null;
}
public byte[] getIconLarge(Request request, Response response)
@RequestMapping(path = "/{itemId}/icon/large", produces = "image/gif")
public byte[] getIconLarge(HttpServletResponse response, @PathVariable int itemId)
{
int itemId = Integer.parseInt(request.params("id"));
ItemEntry item = getItem(itemId);
if (item != null && item.getIcon_large() != null)
{
response.type("image/gif");
response.header(RUNELITE_CACHE, "HIT");
response.setHeader(RUNELITE_CACHE, "HIT");
return item.getIcon_large();
}
item = fetchItem(itemId);
if (item != null)
{
response.type("image/gif");
response.header(RUNELITE_CACHE, "MISS");
response.setHeader(RUNELITE_CACHE, "MISS");
return item.getIcon_large();
}
return null;
}
public ItemPrice getPrice(Request request, Response response)
@RequestMapping("/{itemId}/price")
public ItemPrice getPrice(
HttpServletResponse response,
@PathVariable int itemId,
@RequestParam(required = false) Instant time
)
{
int itemId = Integer.parseInt(request.params("id"));
String ptime = request.params("time");
Instant time = null;
Instant now = Instant.now();
boolean hit = true;
if (ptime != null)
if (time != null && time.isAfter(now))
{
time = Instant.ofEpochMilli(Long.parseLong(ptime));
if (time.isAfter(now))
{
time = now;
}
time = now;
}
ItemEntry item = getItem(itemId);
@@ -263,23 +255,20 @@ public class ItemService
itemPrice.setPrice(priceEntry.getPrice());
itemPrice.setTime(priceEntry.getTime());
response.type("application/json");
response.header(RUNELITE_CACHE, hit ? "HIT" : "MISS");
response.setHeader(RUNELITE_CACHE, hit ? "HIT" : "MISS");
return itemPrice;
}
public SearchResult search(Request request, Response response)
@RequestMapping("/search")
public SearchResult search(HttpServletResponse response, @RequestParam String query)
{
String query = request.queryParams("query");
// rs api seems to require lowercase
query = query.toLowerCase();
SearchResult searchResult = cachedSearches.getIfPresent(query);
if (searchResult != null)
{
response.type("application/json");
response.header(RUNELITE_CACHE, "HIT");
response.setHeader(RUNELITE_CACHE, "HIT");
return searchResult;
}
@@ -314,8 +303,7 @@ public class ItemService
con.commit();
}
response.type("application/json");
response.header(RUNELITE_CACHE, "MISS");
response.setHeader(RUNELITE_CACHE, "MISS");
return searchResult;
}
catch (IOException ex)
@@ -460,7 +448,7 @@ public class ItemService
.addQueryParameter("item", "" + itemId)
.build();
okhttp3.Request request = new okhttp3.Request.Builder()
Request request = new Request.Builder()
.url(itemUrl)
.build();
@@ -476,7 +464,7 @@ public class ItemService
.addPathSegment(itemId + ".json")
.build();
okhttp3.Request request = new okhttp3.Request.Builder()
Request request = new Request.Builder()
.url(priceUrl)
.build();
@@ -490,16 +478,16 @@ public class ItemService
.addQueryParameter("alpha", query)
.build();
okhttp3.Request request = new okhttp3.Request.Builder()
Request request = new Request.Builder()
.url(searchUrl)
.build();
return fetchJson(request, RSSearch.class);
}
private <T> T fetchJson(okhttp3.Request request, Class<T> clazz) throws IOException
private <T> T fetchJson(Request request, Class<T> clazz) throws IOException
{
okhttp3.Response response = RuneliteAPI.CLIENT.newCall(request).execute();
Response response = RuneliteAPI.CLIENT.newCall(request).execute();
if (!response.isSuccessful())
{
@@ -521,11 +509,11 @@ public class ItemService
{
HttpUrl httpUrl = HttpUrl.parse(url);
okhttp3.Request request = new okhttp3.Request.Builder()
Request request = new Request.Builder()
.url(httpUrl)
.build();
okhttp3.Response response = RuneliteAPI.CLIENT.newCall(request).execute();
Response response = RuneliteAPI.CLIENT.newCall(request).execute();
if (!response.isSuccessful())
{

View File

@@ -25,7 +25,6 @@
package net.runelite.http.service.updatecheck;
import com.google.common.base.Suppliers;
import com.google.inject.Inject;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -41,9 +40,12 @@ import net.runelite.http.api.worlds.WorldResult;
import net.runelite.http.service.worlds.WorldsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import spark.Request;
import spark.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/update-check")
public class UpdateCheckService
{
private static final Logger logger = LoggerFactory.getLogger(UpdateCheckService.class);
@@ -58,15 +60,15 @@ public class UpdateCheckService
private final WorldsService worldsService;
private final Supplier<Boolean> updateAvailable = Suppliers.memoizeWithExpiration(this::checkUpdate, 1, TimeUnit.MINUTES);
@Inject
@Autowired
public UpdateCheckService(WorldsService worldsService)
{
this.worldsService = worldsService;
}
public Boolean check(Request request, Response response)
@RequestMapping
public Boolean check()
{
response.type("application/json");
return updateAvailable.get();
}

View File

@@ -32,30 +32,28 @@ import net.runelite.http.api.RuneliteAPI;
import net.runelite.http.api.worlds.World;
import net.runelite.http.api.worlds.WorldResult;
import okhttp3.HttpUrl;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import spark.Request;
import spark.Response;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/worlds")
public class WorldsService
{
private static final HttpUrl WORLD_URL = HttpUrl.parse("http://www.runescape.com/g=oldscape/slr.ws?order=LPWM");
private HttpUrl url = WORLD_URL;
public WorldResult listWorlds(Request request, Response response) throws IOException
{
WorldResult result = listWorlds();
response.type("application/json");
return result;
}
@RequestMapping
public WorldResult listWorlds() throws IOException
{
okhttp3.Request okrequest = new okhttp3.Request.Builder()
Request okrequest = new Request.Builder()
.url(url)
.build();
okhttp3.Response okresponse = RuneliteAPI.CLIENT.newCall(okrequest).execute();
Response okresponse = RuneliteAPI.CLIENT.newCall(okrequest).execute();
byte[] b;
try (ResponseBody body = okresponse.body())

View File

@@ -24,21 +24,25 @@
*/
package net.runelite.http.service.xtea;
import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import java.util.List;
import java.util.stream.Collectors;
import net.runelite.http.api.xtea.XteaKey;
import net.runelite.http.api.xtea.XteaRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import org.springframework.web.bind.annotation.RestController;
import org.sql2o.Connection;
import org.sql2o.Query;
import org.sql2o.Sql2o;
import spark.Request;
import spark.Response;
@RestController
@RequestMapping("/xtea")
public class XteaService
{
private static final Logger logger = LoggerFactory.getLogger(XteaService.class);
@@ -54,16 +58,12 @@ public class XteaService
+ ") ENGINE=InnoDB;";
private final Sql2o sql2o;
private final Gson gson = new Gson();
@Inject
public XteaService(@Named("Runelite SQL2O") Sql2o sql2o)
@Autowired
public XteaService(@Qualifier("Runelite SQL2O") Sql2o sql2o)
{
this.sql2o = sql2o;
}
public void init()
{
try (Connection con = sql2o.beginTransaction())
{
con.createQuery(CREATE_SQL)
@@ -71,10 +71,9 @@ public class XteaService
}
}
public Object submit(Request request, Response response)
@RequestMapping(method = POST)
public Object submit(@RequestBody XteaRequest xteaRequest)
{
XteaRequest xteaRequest = gson.fromJson(request.body(), XteaRequest.class);
try (Connection con = sql2o.beginTransaction())
{
Query query = con.createQuery("insert ignore into xtea (rev, region, key1, key2, key3, key4) values (:rev, :region, :key1, :key2, :key3, :key4)");
@@ -97,19 +96,15 @@ public class XteaService
return "";
}
public List<XteaKey> get(Request request, Response response)
@RequestMapping("/{revision}")
public List<XteaKey> get(@PathVariable int revision)
{
String revStr = request.params("rev");
int revision = Integer.parseInt(revStr);
try (Connection con = sql2o.open())
{
List<XteaEntry> entries = con.createQuery("select * from xtea where rev = :rev")
.addParameter("rev", revision)
.executeAndFetch(XteaEntry.class);
response.type("application/json");
return entries.stream()
.map(XteaService::entryToKey)
.collect(Collectors.toList());

View File

@@ -29,23 +29,4 @@
version="3.1">
<display-name>Runelite API</display-name>
<servlet>
<servlet-name>SparkServlet</servlet-name>
<servlet-class>net.runelite.http.service.SparkServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SparkServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>com.commongroundpublishing.slf4j.impl.ServletContextLoggerSCL</listener-class>
</listener>
<context-param>
<param-name>ServletContextLogger.LEVEL</param-name>
<param-value>INFO</param-value>
</context-param>
</web-app>

View File

@@ -1,121 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.http.service;
import com.commongroundpublishing.slf4j.impl.ServletContextLogger;
import com.google.gson.Gson;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.testing.fieldbinder.Bind;
import com.google.inject.testing.fieldbinder.BoundFieldModule;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.servlet.ServletContext;
import net.runelite.http.api.hiscore.HiscoreResult;
import net.runelite.http.api.hiscore.Skill;
import net.runelite.http.service.hiscore.HiscoreService;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Answers;
import org.mockito.Matchers;
import org.mockito.Mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.mockito.MockitoAnnotations;
import org.sql2o.Sql2o;
import spark.Request;
import spark.Response;
import spark.Spark;
public class ServiceTest
{
private static final String URL_BASE = "http://localhost:4567";
private Service service;
@Bind
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@Named("Runelite SQL2O")
private Sql2o sql2o;
@Bind
@Named("OAuth Client ID")
private String clientId = "test";
@Bind
@Named("OAuth Client Secret")
private String clientSecret = "test";
@Bind
@Mock
private HiscoreService hiscoreService;
@Before
public void before()
{
// Init mocks first, else we're binding null objects
MockitoAnnotations.initMocks(this);
// Inject everything in the test object
Injector injector = Guice.createInjector(BoundFieldModule.of(this));
injector.injectMembers(this);
ServletContextLogger.setServletContext(mock(ServletContext.class));
service = injector.getInstance(Service.class);
service.setupRoutes();
Spark.awaitInitialization();
}
@After
public void after()
{
Spark.stop();
}
@Test
public void testInit() throws Exception
{
HiscoreResult result = new HiscoreResult();
result.setAttack(new Skill(1, 99, 42));
when(hiscoreService.lookup(Matchers.any(Request.class), Matchers.any(Response.class))).thenReturn(result);
URL url = new URL(URL_BASE + "/hiscore?username=zezima");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
Gson gson = new Gson();
HiscoreResult res = gson.fromJson(new InputStreamReader(connection.getInputStream()), HiscoreResult.class);
Assert.assertEquals(result, res);
}
}

View File

@@ -24,23 +24,50 @@
*/
package net.runelite.http.service;
import com.google.gson.Gson;
import spark.ResponseTransformer;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.sql2o.Sql2o;
import org.sql2o.converters.Converter;
import org.sql2o.quirks.NoQuirks;
public class JsonTransformer implements ResponseTransformer
@SpringBootApplication
public class SpringBootWebApplicationTest
{
private final Gson gson = new Gson();
@Override
public String render(Object model) throws Exception
@Bean("Runelite SQL2O")
Sql2o sql2o()
{
if (model == null)
{
// gson turns a null object into "null" which
// causes spark to return http 200 instead of 404
return null;
}
Map<Class, Converter> converters = new HashMap<>();
converters.put(Instant.class, new InstantConverter());
return new Sql2o("jdbc:mysql://192.168.1.2/runelite", "adam", "", new NoQuirks(converters));
return gson.toJson(model);
}
@Bean("OAuth Client ID")
String oauthClientId()
{
return "moo";
}
@Bean("OAuth Client Secret")
String oauthClientSecret()
{
return "moo2";
}
@Test
@Ignore
public void test() throws InterruptedException
{
SpringApplication.run(SpringBootWebApplicationTest.class, new String[0]);
for (;;)
{
Thread.sleep(100L);
}
}
}

View File

@@ -32,9 +32,6 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.mockito.Mockito.mock;
import spark.Request;
import spark.Response;
public class HiscoreServiceTest
{
@@ -94,10 +91,7 @@ public class HiscoreServiceTest
HiscoreService hiscores = new HiscoreService();
hiscores.setUrl(server.url("/"));
Request request = mock(Request.class);
Response response = mock(Response.class);
HiscoreResult result = hiscores.lookup(request, response);
HiscoreResult result = hiscores.lookup("zezima");
Assert.assertEquals(50, result.getAttack().getLevel());
Assert.assertEquals(159727L, result.getFishing().getExperience());

View File

@@ -34,7 +34,7 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import spark.utils.IOUtils;
import org.sql2o.tools.IOUtils;
public class WorldsServiceTest
{