Using proxy for specific HTTPS request in java - java

I have requirement to pass HTTPs calls of some specific URL via proxy and rest direct. I have written my own custom proxy implementation using ProxySelector of java.net. It is working fine for HTTP calls ( I can see in proxy access logs in that case) but in case of HTTPS calls it seems it is not using proxy).Am I missing something here.? Proxy server is configured properly and its access log is updating when some HTTPS calls passed from browser with proxy.
package com.blabla.proxy;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.vuclip.pubsub.logging.PubSubUtil;
import com.vuclip.pubsub.logging.client.GooglePubSubClient;
public class CustomProxySelector extends ProxySelector {
private static final Logger LOGGER = LogManager.getLogger(PubSubUtil.class);
private final ProxySelector def;
private final String PUB_SUB_URL = "pubsub.googleapis.com";
List<Proxy> proxyList = new ArrayList<Proxy>();
private Proxy proxy=null;
public CustomProxySelector(ProxySelector aDefault) {
this.def = aDefault;
}
#Override
public void connectFailed(URI arg0, SocketAddress soc, IOException ex) {
LOGGER.error("Error in connecting to proxcy "+soc +" for pubsub :"+ ex);
}
#Override
public List<Proxy> select(URI uri) {
if ("https".equalsIgnoreCase(uri.getScheme()) && uri.getHost().startsWith(PUB_SUB_URL)
&& GooglePubSubClient.isProxyEnabled()) {
synchronized (this) {
if (proxy == null) {
proxy = new Proxy(Proxy.Type.SOCKS,
new InetSocketAddress(GooglePubSubClient.getProxyHost(), GooglePubSubClient.getProxyPort()));
}
}
proxyList.add(proxy);
LOGGER.debug("ProxyList:" + proxyList);
return proxyList;
}
proxyList = def.select(uri);
LOGGER.debug("Default proxy list : " + proxyList);
return proxyList;
}
}

I changed Proxy.Type.SOCKS to Proxy.Type.HTTP and it worked for me.

Related

How to create a working TCP Server socket in spring boot and how to handle the incoming message?

I have tried to implement a TCP server socket with spring integration in an allready existing spring boot application, but I am facing a problem and this problem drives me crazy...
The client is sending a message (a byte array) to the server and timesout. That's it.
I am not receiving any exceptions from the server. It seems I have provided the wrong port or somthing but after checking the port, I am sure it is the right one.
This is my annotation based configuration class:
import home.brew.server.socket.ServerSocketHandler;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.ip.dsl.Tcp;
#Log4j2
#Configuration
#EnableIntegration
public class TcpServerSocketConfiguration {
#Value("${socket.port}")
private int serverSocketPort;
#Bean
public IntegrationFlow server(ServerSocketHandler serverSocketHandler) {
TcpServerConnectionFactorySpec connectionFactory =
Tcp.netServer(socketPort)
.deserializer(new CustomSerializerDeserializer())
.serializer(new CustomSerializerDeserializer())
.soTcpNoDelay(true);
TcpInboundGatewaySpec inboundGateway =
Tcp.inboundGateway(connectionFactory);
return IntegrationFlows
.from(inboundGateway)
.handle(serverSocketHandler::handleMessage)
.get();
}
#Bean
public ServerSocketHandler serverSocketHandler() {
return new ServerSocketHandler();
}
}
I wanted to make the receive functionality work before I try to send an answer, so that's why have a minimal configuration.
And the following class should process the received message from the server socket
import lombok.extern.log4j.Log4j2;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;
#Log4j2
public class ServerSocketHandler {
public String handleMessage(Message<?> message, MessageHeaders messageHeaders) {
log.info(message.getPayload());
// TODO implement something useful to process the incoming message here...
return message.getPayload().toString();
}
}
The handler method from above was never invoked even once!
I have googled for some example implementations or tutorials but I haven't found anyhing what worked for me.
I allready tried the implementations of these sites:
https://vispud.blogspot.com/2019/03/how-to-implement-simple-echo-socket.html
https://docs.spring.io/spring-integration/docs/current/reference/html/ip.html#note-nio
Spring Boot TCP Client
and a bunch of sites more... but nothing helped me :-(
UPDATE 1
I have implemented a custom serializer/deserializer:
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.springframework.core.serializer.Deserializer;
import org.springframework.core.serializer.Serializer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
#Log4j2
#Data
public class CustomSerializerDeserializer implements Serializer<byte[]>,
Deserializer<byte[]> {
#Override
public byte[] deserialize(InputStream inputStream) throws IOException {
return inputStream.readAllBytes();
}
#Override
public void serialize(byte[] object, OutputStream outputStream) throws IOException {
outputStream.write(object);
}
}
After the client have sent a message, the custom serializer is invoked but the content ist always empty. I have no idea why.... The serializer needs a lot of time to read all bytes from the stream and in the end it is empty. The procedure is repeating all the time, so I think I have build an infinty loop by accident...
UPDATE 2
I have captured the communication between Client and server socket:
It looks like I am stuck in the handshake and therefore there is no payload...
So if anybody could help me out with this, I would be very thankful and if you need some more information, just let me know.
Thanks in advance!
Well, after a few days of analysing and coding, I found the best solution for me to handle TCP socket communications using spring integration. For other developers who are struggling with the same problems. Here is what I've done so far.
This class contains a - for me working - annotation based TCP socket connection configuration
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.ip.IpHeaders;
import org.springframework.integration.ip.tcp.TcpInboundGateway;
import org.springframework.integration.ip.tcp.TcpOutboundGateway;
import org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpNetServerConnectionFactory;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.web.context.request.RequestContextListener;
/**
* Spring annotation based configuration
*/
#Configuration
#EnableIntegration
#IntegrationComponentScan
public class TcpServerSocketConfiguration {
public static final CustomSerializerDeserializer SERIALIZER = new CustomSerializerDeserializer();
#Value("${socket.port}")
private int socketPort;
/**
* Reply messages are routed to the connection only if the reply contains the ip_connectionId header
* that was inserted into the original message by the connection factory.
*/
#MessagingGateway(defaultRequestChannel = "toTcp")
public interface Gateway {
void send(String message, #Header(IpHeaders.CONNECTION_ID) String connectionId);
}
#Bean
public MessageChannel fromTcp() {
return new DirectChannel();
}
#Bean
public MessageChannel toTcp() {
return new DirectChannel();
}
#Bean
public AbstractServerConnectionFactory serverCF() {
TcpNetServerConnectionFactory serverCf = new TcpNetServerConnectionFactory(socketPort);
serverCf.setSerializer(SERIALIZER);
serverCf.setDeserializer(SERIALIZER);
serverCf.setSoTcpNoDelay(true);
serverCf.setSoKeepAlive(true);
// serverCf.setSingleUse(true);
// final int soTimeout = 5000;
// serverCf.setSoTimeout(soTimeout);
return serverCf;
}
#Bean
public AbstractClientConnectionFactory clientCF() {
TcpNetClientConnectionFactory clientCf = new TcpNetClientConnectionFactory("localhost", socketPort);
clientCf.setSerializer(SERIALIZER);
clientCf.setDeserializer(SERIALIZER);
clientCf.setSoTcpNoDelay(true);
clientCf.setSoKeepAlive(true);
// clientCf.setSingleUse(true);
// final int soTimeout = 5000;
// clientCf.setSoTimeout(soTimeout);
return clientCf;
}
#Bean
public TcpInboundGateway tcpInGate() {
TcpInboundGateway inGate = new TcpInboundGateway();
inGate.setConnectionFactory(serverCF());
inGate.setRequestChannel(fromTcp());
inGate.setReplyChannel(toTcp());
return inGate;
}
#Bean
public TcpOutboundGateway tcpOutGate() {
TcpOutboundGateway outGate = new TcpOutboundGateway();
outGate.setConnectionFactory(clientCF());
outGate.setReplyChannel(toTcp());
return outGate;
}
This class contains a custom serializer and deserialiser
import lombok.extern.log4j.Log4j2;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.serializer.Deserializer;
import org.springframework.core.serializer.Serializer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
/**
* A custom serializer for incoming and/or outcoming messages.
*/
#Log4j2
public class CustomSerializerDeserializer implements Serializer<byte[]>, Deserializer<byte[]> {
#NotNull
#Override
public byte[] deserialize(InputStream inputStream) throws IOException {
byte[] message = new byte[0];
if (inputStream.available() > 0) {
message = inputStream.readAllBytes();
}
log.debug("Deserialized message {}", new String(message, StandardCharsets.UTF_8));
return message;
}
#Override
public void serialize(#NotNull byte[] message, OutputStream outputStream) throws IOException {
log.info("Serializing {}", new String(message, StandardCharsets.UTF_8));
outputStream.write(message);
outputStream.flush();
}
}
In the following classes you can implement some buisness logic to process incoming ...
import lombok.extern.log4j.Log4j2;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.stereotype.Component;
#Log4j2
#Component
#MessageEndpoint
public class ClientSocketHandler {
#ServiceActivator(inputChannel = "toTcp")
public byte[] handleMessage(byte[] msg) {
// TODO implement some buisiness logic here
return msg;
}
}
and outgoing messages.
import lombok.extern.log4j.Log4j2;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.stereotype.Component;
#Log4j2
#Component
#MessageEndpoint
public class ClientSocketHandler {
#ServiceActivator(inputChannel = "toTcp")
public byte[] handleMessage(byte[] msg) {
// implement some business logic here
return msg;
}
}
Hope it helps. ;-)
How are you communicating with this server? By default the connection factory is configured to require the input to be terminated by CRLF (e.g. Telnet). You have to configure a different deserializer if your client uses something else to indicate a message end.
Also, your method signature is incorrect; it should be:
public String handleMessage(byte[] message, MessageHeaders messageHeaders) {
String string = new String(message);
System.out.println(string);
return string.toUpperCase();
}
This works fine for me with Telnet:
$ telnet localhost 1234
Trying ::1...
Connected to localhost.
Escape character is '^]'.
foo
FOO
^]
telnet> quit
Connection closed.
And here is a version that works with just LF (e.g. netcat):
#Bean
public IntegrationFlow server(ServerSocketHandler serverSocketHandler) {
return IntegrationFlows.from(Tcp.inboundGateway(
Tcp.netServer(1234)
.deserializer(TcpCodecs.lf())
.serializer(TcpCodecs.lf())))
.handle(serverSocketHandler::handleMessage)
.get();
}
$ nc localhost 1234
foo
FOO
^C

Use Actors to send data to Akka websockets

I am using Akka websockets to push data to some client.
This is what I have done so far:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.Http;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.model.ws.Message;
import akka.http.javadsl.model.ws.WebSocket;
import akka.japi.Function;
import akka.stream.ActorMaterializer;
import akka.stream.Materializer;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
public class Server {
public static HttpResponse handleRequest(HttpRequest request) {
System.out.println("Handling request to " + request.getUri());
if (request.getUri().path().equals("/greeter")) {
final Flow<Message, Message, NotUsed> greeterFlow = greeterHello();
return WebSocket.handleWebSocketRequestWith(request, greeterFlow);
} else {
return HttpResponse.create().withStatus(404);
}
}
public static void main(String[] args) throws Exception {
ActorSystem system = ActorSystem.create();
try {
final Materializer materializer = ActorMaterializer.create(system);
final Function<HttpRequest, HttpResponse> handler = request -> handleRequest(request);
CompletionStage<ServerBinding> serverBindingFuture = Http.get(system).bindAndHandleSync(handler,
ConnectHttp.toHost("localhost", 8080), materializer);
// will throw if binding fails
serverBindingFuture.toCompletableFuture().get(1, TimeUnit.SECONDS);
System.out.println("Press ENTER to stop.");
new BufferedReader(new InputStreamReader(System.in)).readLine();
} finally {
system.terminate();
}
}
public static Flow<Message, Message, NotUsed> greeterHello() {
return Flow.fromSinkAndSource(Sink.ignore(),
Source.single(new akka.http.scaladsl.model.ws.TextMessage.Strict("Hello!")));
}
}
At the client side, I am successfully receiving a 'Hello!' message.
However, now I want to send data dynamically (preferably from an Actor), something like this:
import akka.actor.ActorRef;
import akka.actor.UntypedActor;
public class PushActor extends UntypedActor {
#Override
public void onReceive(Object message) {
if (message instanceof String) {
String statusChangeMessage = (String) message;
// How to push this message to a socket ??
} else {
System.out.println(String.format("'%s':\nReceived unknown message '%s'!", selfActorPath, message));
}
}
}
I am unable to find any example regarding this online.
The following is the software stack being used:
Java 1.8
akka-http 10.0.10
One - not necessarily very elegant - way of doing this is to use Source.actorRef and send the materialized actor somewhere (maybe a router actor?) depending on your requirements.
public static Flow<Message, Message, NotUsed> greeterHello() {
return Flow.fromSinkAndSourceMat(Sink.ignore(),
Source.actorRef(100, OverflowStrategy.fail()),
Keep.right()).mapMaterializedValue( /* send your actorRef to a router? */);
}
Whoever receives the actorRefs of the connected clients must be responsible for routing messages to them.

Using Selenium RemoteWebDriver behind corporate proxy

How can I connect to a selenium grid such as BrowserStack via RemoteWebDriver from behind a corporate proxy?
The application under test is outside the proxy and freely accessible from BrowserStack.
This Using Selenium RemoteWebDriver behind corporate proxy (Java) stackoverflow question asked the same question but I couldn't follow the accepted answer.
I managed to get something working based on the accepted answer in the linked stackoverflow question, here's my implementation in case anyone else is stuck on the same problem:
Example
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClientBuilder;
import org.openqa.selenium.remote.CommandInfo;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.HttpCommandExecutor;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.http.HttpClient.Factory;
public class Example {
public RemoteWebDriver connectViaProxy(DesiredCapabilities caps) {
String proxyHost = "?";
int proxyPort = 8080;
String proxyUserDomain = "?";
String proxyUser = "?";
String proxyPassword = "?";
URL url;
try {
url = new URL("http://bsuser:bspassword#hub.browserstack.com/wd/hub");
} catch (MalformedURLException e) {
throw new RuntimeException(e.getMessage(), e);
}
HttpClientBuilder builder = HttpClientBuilder.create();
HttpHost proxy = new HttpHost(proxyHost, proxyPort);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(proxyHost, proxyPort), new NTCredentials(proxyUser, proxyPassword, getWorkstation(), proxyUserDomain));
if (url.getUserInfo() != null && !url.getUserInfo().isEmpty()) {
credsProvider.setCredentials(new AuthScope(url.getHost(), (url.getPort() > 0 ? url.getPort() : url.getDefaultPort())), new UsernamePasswordCredentials(url.getUserInfo()));
}
builder.setProxy(proxy);
builder.setDefaultCredentialsProvider(credsProvider);
Factory factory = new MyHttpClientFactory(builder);
HttpCommandExecutor executor = new HttpCommandExecutor(new HashMap<String, CommandInfo>(), url, factory);
return new RemoteWebDriver(executor, caps);
}
private String getWorkstation() {
Map<String, String> env = System.getenv();
if (env.containsKey("COMPUTERNAME")) {
// Windows
return env.get("COMPUTERNAME");
} else if (env.containsKey("HOSTNAME")) {
// Unix/Linux/MacOS
return env.get("HOSTNAME");
} else {
// From DNS
try
{
return InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException ex)
{
return "Unknown";
}
}
}
}
MyHttpClientFactory
import java.net.URL;
import org.apache.http.impl.client.HttpClientBuilder;
import org.openqa.selenium.remote.internal.ApacheHttpClient;
public class MyHttpClientFactory implements org.openqa.selenium.remote.http.HttpClient.Factory {
final HttpClientBuilder builder;
public MyHttpClientFactory(HttpClientBuilder builder) {
this.builder = builder;
}
#Override
public org.openqa.selenium.remote.http.HttpClient createClient(URL url) {
return new ApacheHttpClient(builder.build(), url);
}
}
Adding to the answer above by Andrew, to make this work with Appium change the
HttpCommandExecutor executor = new HttpCommandExecutor(new HashMap<String, CommandInfo>(), url, factory);
to
HttpCommandExecutor executor = new HttpCommandExecutor(MobileCommand.commandRepository, url, factory);
I've reworked Andrew Sumner's solution slightly and taken some out in case someone like me wants to just quickly funnel their WebDriver traffic through Fiddler to see the traffic.
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import org.apache.http.HttpHost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.openqa.selenium.ie.InternetExplorerOptions;
import org.openqa.selenium.remote.CommandInfo;
import org.openqa.selenium.remote.HttpCommandExecutor;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpClient.Factory;
import org.openqa.selenium.remote.internal.ApacheHttpClient;
public class ProxiedRemoteExample {
private static final String PROXY_HOST = "localhost";
private static final int PROXY_PORT = 8888;
public ProxiedRemoteExample() throws MalformedURLException {
InternetExplorerOptions ieOptions = new InternetExplorerOptions();
RemoteWebDriver driver = new RemoteWebDriver(new HttpCommandExecutor(new HashMap<String, CommandInfo>(),
new URL("http://localhost:5555/"), new Factory() {
private HttpClientBuilder builder;
{
builder = HttpClientBuilder.create();
builder.setProxy(new HttpHost(PROXY_HOST, PROXY_PORT));
}
#Override
public HttpClient createClient(URL url) {
return new ApacheHttpClient(builder.build(), url);
}
}), ieOptions);
}
}
With
org.seleniumhq.selenium:selenium-java:4.0.0-beta-3 I had to apply proxy settings in the following way:
configure async http client to use proxy settings
create ahc.properties file under org/asynchttpclient/config folder
file content: org.asynchttpclient.useProxyProperties = true
configure JVM proxy properties
System.getProperties().setProperty("http.proxyHost", "yourProxyHost")
System.getProperties().setProperty("http.proxyPort", "yourProxyPort")

Grizzly and ServletContainerContext

I'm trying to get hold of some injected context (for example Session or HttpServletRequest) in a Servlet I've written, running on Grizzly, but nothing I do seems to work. The whole process seems to stall rather prematurely with the following error:
SEVERE: Missing dependency for field: javax.servlet.http.HttpServletRequest com.test.server.LolCat.hsr
The server is dead simple, it consists of two files, the static entry point (Main.java):
package com.test.server;
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.grizzly.http.server.HttpServer;
import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
import com.sun.jersey.api.core.ClassNamesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig;
public class Main {
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost/").port(8080).build();
}
public static final URI BASE_URI = getBaseURI();
public static void main(String[] args) throws IOException {
ResourceConfig rc = new ClassNamesResourceConfig(LolCat.class);
HttpServer httpServer = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
System.in.read();
httpServer.stop();
}
}
and the serlvet (LolCat.java):
package com.test.server;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
#Path(value = "/lol")
public class LolCat {
#Context HttpServletRequest hsr;
#GET
#Path(value="/cat")
public String list() {
return "meow";
}
}
Specifically, it's the #Context-line in the above source file that is the source and solution to all my problems. I need it, and according to everything I've read about Jersey and Servlets it should work, but alas it does not. I've also tried using GrizzlyWebContainerFactory instead of the GrizzlyServerFactory, but to no avail.
For reference, the project is compiled with the following dependencies:
org.glassfish.grizzly:grizzly-framework:jar:2.2.21
org.glassfish.grizzly:grizzly-http:jar:2.2.21
org.glassfish.grizzly:grizzly-http-servlet:jar:2.2.21
org.glassfish.grizzly:grizzly-http-server:jar:2.2.21
com.sun.jersey:jersey-server:jar:1.17
com.sun.jersey:jersey-servlet:jar:1.17
com.sun.jersey:jersey-core:jar:1.17
javax.servlet:javax.servlet-api:jar:2.5.0
com.sun.jersey:jersey-grizzly2:jar:1.17
com.sun.jersey:jersey-grizzly2-servlet:jar:1.17
asm:asm:jar:3.3.1
This Main class works fine for me:
package com.test.server;
import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import com.sun.jersey.api.core.ClassNamesResourceConfig;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.grizzly.http.server.Response;
import org.glassfish.grizzly.servlet.ServletRegistration;
import org.glassfish.grizzly.servlet.WebappContext;
public class Main {
private static final String JERSEY_SERVLET_CONTEXT_PATH = "";
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost").port(8080).path("/").build();
}
public static final URI BASE_URI = getBaseURI();
public static void main(String[] args) throws IOException {
// Create HttpServer and register dummy "not found" HttpHandler
HttpServer httpServer = GrizzlyServerFactory.createHttpServer(BASE_URI, new HttpHandler() {
#Override
public void service(Request rqst, Response rspns) throws Exception {
rspns.setStatus(404, "Not found");
rspns.getWriter().write("404: not found");
}
});
// Initialize and register Jersey Servlet
WebappContext context = new WebappContext("WebappContext", JERSEY_SERVLET_CONTEXT_PATH);
ServletRegistration registration = context.addServlet("ServletContainer", ServletContainer.class);
registration.setInitParameter(ServletContainer.RESOURCE_CONFIG_CLASS,
ClassNamesResourceConfig.class.getName());
registration.setInitParameter(ClassNamesResourceConfig.PROPERTY_CLASSNAMES, LolCat.class.getName());
registration.addMapping("/*");
context.deploy(httpServer);
System.in.read();
httpServer.stop();
}
}
Try http://localhost:8080/lol/cat in your browser.
You can change JERSEY_SERVLET_CONTEXT_PATH to update Servlet's context-path.
As per developers explanations - Grizzly is not fully compliant to JAX-RS 2.0 so there will be no official contexts injections/wrapping. See Jersey Bug-1960
Applicable for Jersey + Grizzly version 2.7+
Luckily there is a way to inject Grizzly request/response objects. Kind of tricky but works
Code sample provided in one of Jersey's unit tests. See Jersey container test
So code fragment will be:
import javax.inject.Inject;
import javax.inject.Provider;
public someclass {
#Inject
private Provider<Request> grizzlyRequestProvider;
public void method() {
if (grizzlyRequestProvider != null) {
Request httpRequest = grizzlyRequestProvider.get();
// Extract what you need
}
}
}
Works fine both for filters and service methods
You can also manually register a ResourceContext
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(getBaseURI());
WebappContext context = new WebappContext("WebappContext", "/api");
ServletRegistration registration = context.addServlet("ServletContainer",
new ServletContainer(config));
registration.addMapping("/*");
context.deploy(httpServer);
Where config is your resource context.
Try something like this :-
public class Main {
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost/").port(8080).build();
}
public static void main(String[] args) throws IOException {
ResourceConfig rc = new ResourceConfig().packages("com.example");//path to you class files
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc);
System.in.read();
httpServer.stop();
}
}

HTTP Request Object

Is there an object within the standard Java SE that can accept a HTTP request from a socket? I have found how to create and send one, however I have not found a way to retrieve a HTTP object from a socket. I can create one my self, but I would rather rely on a heavily tested object.
This seems like something that would be readily available given the structure of JSP.
There is a small HTTP server in the Java 6 SDK (not sure if it will be in the JRE or in non-Sun JVM's).
From http://www.java2s.com/Code/Java/JDK-6/LightweightHTTPServer.htm :
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class HttpServerDemo {
public static void main(String[] args) throws IOException {
InetSocketAddress addr = new InetSocketAddress(8080);
HttpServer server = HttpServer.create(addr, 0);
server.createContext("/", new MyHandler());
server.setExecutor(Executors.newCachedThreadPool());
server.start();
System.out.println("Server is listening on port 8080" );
}
}
class MyHandler implements HttpHandler {
public void handle(HttpExchange exchange) throws IOException {
String requestMethod = exchange.getRequestMethod();
if (requestMethod.equalsIgnoreCase("GET")) {
Headers responseHeaders = exchange.getResponseHeaders();
responseHeaders.set("Content-Type", "text/plain");
exchange.sendResponseHeaders(200, 0);
OutputStream responseBody = exchange.getResponseBody();
Headers requestHeaders = exchange.getRequestHeaders();
Set<String> keySet = requestHeaders.keySet();
Iterator<String> iter = keySet.iterator();
while (iter.hasNext()) {
String key = iter.next();
List values = requestHeaders.get(key);
String s = key + " = " + values.toString() + "\n";
responseBody.write(s.getBytes());
}
responseBody.close();
}
}
}
Yeah, you make a new HTTP Request object from what you accept on the socket. What you do after that is up to you, but it should probably involve an HTTP Response.
import java.io.*;
import java.net.*;
import java.util.*;
public final class WebServer {
public static void main(String args[]) throws Exception {
int PORT = 8080;
ServerSocket listenSocket = new ServerSocket(PORT);
while(true) {
HttpRequest request = new HttpRequest(listenSocket.accept());
Thread thread = new Thread(request);
thread.start();
}
}
}
From: http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=396
There's some more work to be done in the tutorial, but it does look nice.
It looks like you are looking for a Servlet. A servlet is an API that lets you receive and respond to an HTTP request.
Your servlet gets deployed in a container, which is basically the actual Web server that will take care of all the protocol complexities. (The most populare are Tomcat and Jetty)

Categories

Resources