tutorial services restful jax example rest heroku jersey jax-rs grizzly

services - ¿Cómo averiguar la IP de la solicitud RESTful entrante usando JAX-RS en Heroku?



restful java (3)

Estoy escribiendo un servicio RESTful de Java alojado en Heroku basado en un ejemplo -> https://api.heroku.com/myapps/template-java-jaxrs/clone

Mi servicio de muestra es:

package com.example.services; import com.example.models.Time; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("/time") @Produces(MediaType.APPLICATION_JSON) public class TimeService { @GET public Time get() { return new Time(); } }

Mi principal es:

public class Main { public static final String BASE_URI = getBaseURI(); /** * @param args */ public static void main(String[] args) throws Exception{ final Map<String, String> initParams = new HashMap<String, String>(); initParams.put("com.sun.jersey.config.property.packages","services.contracts"); System.out.println("Starting grizzly..."); SelectorThread threadSelector = GrizzlyWebContainerFactory.create(BASE_URI, initParams); System.out.println(String.format("Jersey started with WADL available at %sapplication.wadl.",BASE_URI, BASE_URI)); } private static String getBaseURI() { return "http://localhost:"+(System.getenv("PORT")!=null?System.getenv("PORT"):"9998")+"/"; } }

Mi pregunta es ¿cómo puedo averiguar en mi servicio la dirección IP y la combinación de puertos de donde proviene la solicitud? He leído cosas en @Context que inyecta javax.ws.rs.core.HttpHeaders, javax.ws.rs.core.Request, etc. Sin embargo, no hay información de IP o puerto entrante presente.

Sé que si implementa com.sun.grizzly.tcp.Adapter, puede hacer algo como:

public static void main(String[] args) { SelectorThread st = new SelectorThread(); st.setPort(8282); st.setAdapter(new EmbeddedServer()); try { st.initEndpoint(); st.startEndpoint(); } catch (Exception e) { System.out.println("Exception in SelectorThread: " + e); } finally { if (st.isRunning()) { st.stopEndpoint(); } } } public void service(Request request, Response response) throws Exception { String requestURI = request.requestURI().toString(); System.out.println("New incoming request with URI: " + requestURI); System.out.println("Request Method is: " + request.method()); if (request.method().toString().equalsIgnoreCase("GET")) { response.setStatus(HttpURLConnection.HTTP_OK); byte[] bytes = "Here is my response text".getBytes(); ByteChunk chunk = new ByteChunk(); response.setContentLength(bytes.length); response.setContentType("text/plain"); chunk.append(bytes, 0, bytes.length); OutputBuffer buffer = response.getOutputBuffer(); buffer.doWrite(chunk, response); response.finish(); } } public void afterService(Request request, Response response) throws Exception { request.recycle(); response.recycle(); }

y acceso

request.remoteAddr()

Pero me gustaría separar mi API RESTful de una manera más estructurada, como en mi primera implementación.

Cualquier ayuda sería muy apreciada. ¡Gracias!


Basado en la fusión @ user647772 y @Ethan. Gracias a ellos ;)

Inyectar HttpServletRequest:

@GET @Produces(MediaType.TEXT_PLAIN) public Response getFromp(@Context HttpServletRequest req) { String from = _getUserFrom(req); return Response.ok(from).build(); } private String _getUserFrom(HttpServletRequest req) { String xForwardedFor = req.getHeader("X-Forwarded-For"); xForwardedFor = xForwardedFor != null && xForwardedFor.contains(",") ? xForwardedFor.split(",")[0]:xForwardedFor; String remoteHost = req.getRemoteHost(); String remoteAddr = req.getRemoteAddr(); int remotePort = req.getRemotePort(); StringBuffer sb = new StringBuffer(); if (remoteHost != null && !"".equals(remoteHost) && !remoteHost.equals(remoteAddr)) { sb.append(remoteHost).append(" "); } if (xForwardedFor != null && !"".equals(xForwardedFor)) { sb.append(xForwardedFor).append("(fwd)=>"); } if (remoteAddr != null || !"".equals(remoteAddr)) { sb.append(remoteAddr).append(":").append(remotePort); } return sb.toString(); }


Como dijo Luke, al usar Heroku, el host remoto es el nivel de aplicación AWS, por lo tanto, la dirección IP EC2.

El encabezado "X-Forwarded-For" es la respuesta:

String ip = "0.0.0.0"; try { ip = req.getHeader("X-Forwarded-For").split(",")[0]; } catch (Exception ignored){}


Puede inyectar HttpServletRequest :

@GET @Produces(MediaType.TEXT_PLAIN) public Response getIp(@Context HttpServletRequest req) { String remoteHost = req.getRemoteHost(); String remoteAddr = req.getRemoteAddr(); int remotePort = req.getRemotePort(); String msg = remoteHost + " (" + remoteAddr + ":" + remotePort + ")"; return Response.ok(msg).build(); }