Setup: I have set up embedded jetty (v9.1) to serve static files with the setDirectoriesListed(true) and the code I am using is below:
// Create a basic Jetty server object that will listen on port 8080. Note that if you set this to port 0
// then a randomly available port will be assigned that you can either look in the logs for the port,
// or programmatically obtain it for use in test cases.
Server server = new Server(9090);
// Create the ResourceHandler. It is the object that will actually handle the request for a given file. It is
// a Jetty Handler object so it is suitable for chaining with other handlers as you will see in other examples.
ResourceHandler resource_handler = new ResourceHandler();
// Configure the ResourceHandler. Setting the resource base indicates where the files should be served out of.
// In this example it is the current directory but it can be configured to anything that the jvm has access to.
resource_handler.setDirectoriesListed(true);
resource_handler.setWelcomeFiles(new String[]{ "index.html" });
resource_handler.setResourceBase(".");
// Add the ResourceHandler to the server.
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
server.setHandler(handlers);
// Start things up! By using the server.join() the server thread will join with the current thread.
// See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details.
server.start();
server.join();
This code is originally from here.
When I navigate to the address http://localhost:9090/, I see the files listed in the directory and I am able to click and open individual text files.
Problem: For some inexplicable reason, only when I click on a file of 0 bytes (aka it's an empty file, but still shown in the browser), the connection tries to load but eventually times out (30 seconds) and I get a response in safari saying the "server unexpectedly dropped the connection." In addition, when I make a HttpURLConnection to the 0 byte file, I get a content length returned of -1; This of course is only for empty files.
Expected Behavior as seen in standalone Jetty: When I use standalone jetty and serve the same files, I am able to "open" the empty file which just returns a blank page in a web browser. When using the HttpURLConnection, I get a content length of 0.
While this seems like a "pointless" task, one server is programmatically syncing with the embedded jetty server (so I want those empty files to sync). I imagine it has something to do with the resource handler seeing 0 bytes as it serves the static content, but I'm not too sure how to get the same behavior of the standalone jetty server as right now, it errors when trying to pull the empty files.
Thanks!
Your code works, as-is, at least on Jetty 9.2.7.v20140116
Full example I used:
package jetty;
import java.io.File;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
public class SimpleResources
{
public static void main(String[] args)
{
Server server = new Server(9090);
String resourceBase = System.getProperty("resourceBase", ".");
System.err.printf("Resource Base is: %s%n", new File(resourceBase).getAbsolutePath());
ResourceHandler resource_handler = new ResourceHandler();
resource_handler.setDirectoriesListed(true);
resource_handler.setWelcomeFiles(new String[] { "index.html" });
resource_handler.setResourceBase(resourceBase);
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
server.setHandler(handlers);
try
{
server.start();
server.join();
}
catch (Throwable t)
{
t.printStackTrace(System.err);
}
}
}
I ran it pointing the -DresourceBase system property to a directory that has the following ...
$ ls -la
total 8
drwxrwxr-x. 2 joakim joakim 4096 Jan 20 11:53 .
drwxrwxr-x. 3 joakim joakim 4096 Jan 20 11:53 ..
-rw-rw-r--. 1 joakim joakim 0 Jan 20 11:53 foo.txt
And once running the console shows ...
2015-01-20 11:55:07.788:INFO::main: Logging initialized #68ms
Resource Base is: /home/joakim/code/Jetty/empties
2015-01-20 11:55:07.837:INFO:oejs.Server:main: jetty-9.2.7.v20150116
2015-01-20 11:55:07.860:INFO:oejs.ServerConnector:main: Started ServerConnector#5461eda{HTTP/1.1}{0.0.0.0:9090}
2015-01-20 11:55:07.861:INFO:oejs.Server:main: Started #144ms
With a test request like such ...
$ curl --dump-header - http://localhost:9090/foo.txt
HTTP/1.1 200 OK
Date: Tue, 20 Jan 2015 18:55:39 GMT
Content-Type: text/plain
Content-Length: 0
Server: Jetty(9.2.7.v20150116)
Update:
Works as-is with no modifications on the following versions of jetty as well (didn't do an exhaustive test of versions, just a few older ones as well)
9.2.6.v20141205 - Identical Results
9.2.4.v20141103 - Identical Results
9.2.1.v20140609 - Identical Results
9.1.5.v20140505 - No Date in response headers, rest is the same (yes, it also sends Content-Length: 0)
Related
We are planning to implement http2 in a loopback 4 application. We had used http, socket servers but never http2.
What is the procedure to use http2 in my application?
Here's what you have to do in your existing app:
Step 1: Install spdy
npm i spdy
Step 2: Configure index.ts
Change your main function in src/index.ts with this:
import spdy from "spdy";
export async function main(options: ApplicationConfig = {}) {
// specify cert and key file paths for SSL
const serverOptions: spdy.ServerOptions = {
key: fs.readFileSync(
path.join(__dirname, '..', 'keys', 'localhost-privkey.pem'),
),
cert: fs.readFileSync(
path.join(__dirname, '..', 'keys', 'localhost-cert.pem'),
),
};
// setting listenOnStart to false will not start the default httpServer
options.rest.listenOnStart = false;
// Replace YourApplication with your class
const app = new YourApplication(options);
await app.boot();
await app.start();
// create server
const server = spdy.createServer(serverOptions, app.requestHandler);
// to avoid process exit on warnings
server.on('warning', console.warn);
server.listen(3000, () => {
console.log('Listening on https://localhost:3000/');
});
return app;
}
All we're doing in the above code is, preventing the default http server from being started and starting the server using spdy with loopback's request handler app.requestHandler that will be used for all incoming request.
Check out this pastebin containing entire index.ts file content after the changes.
To generate certificate and keys for localhost use:
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
-keyout localhost-privkey.pem -out localhost-cert.pem
You may need to allow self-signed certificates in Chrome as well for /explorer to work as expected.
And that's it, you can now run your app, and enjoy the power of http2 :)
Blog Post: https://shubham-web.medium.com/how-to-use-http2-in-loopback-4-applications-5e83881c7b38
I have written a code in poco c++ library that is supposed to send a request to the server to get some data. The is running from inside a docker container. And I am getting a "hostname not resolved" error. The sample code is as follow
//initialize session
Poco::SharedPtr<InvalidCertificateHandler> ptrCert = new AcceptCertificateHandler(false);
_ptrContext = new Context(Context::TLSV1_2_CLIENT_USE, "", "", "", Context::VERIFY_RELAXED, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:#STRENGTH");
_ptrContext->enableSessionCache(true);
// Disable SSL versions 2 & 3 and TLS versions 1.0 & 1.1
_ptrContext->disableProtocols(Poco::Net::Context::PROTO_SSLV2 | Poco::Net::Context::PROTO_SSLV3 | Poco::Net::Context::PROTO_TLSV1 | Poco::Net::Context::PROTO_TLSV1_1);
SSLManager::instance().initializeClient(0, ptrCert, _ptrContext);
_httpsession_secure = new HTTPSClientSession(_hostname, _port);
//build request
Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_POST, uri, Poco::Net::HTTPMessage::HTTP_1_1);
req.setContentLength(http_body.length());
req.setContentType("application/x-www-form-urlencoded");
// Send request
std::ostream &os = _httpsession_secure->sendRequest(req);
os << http_body;
// Wait for response
Poco::Net::HTTPResponse res;
std::istream &rs = _httpsession_secure->receiveResponse(res);
I have run a curl command as the CMD entry in the docker container, and the command is executing properly and giving the result. so that means the host is accessible inside the container. When I execute the code inside the container, it is failing. So I am surely missing something in the code. Please guide.
As per your answer to a my question in the comments, you are using:
_httpsession_secure = new HTTPSClientSession(_hostname, _port);
where _hostname is of the form to https://somehost.somedomain.
This is wrong, you must not pass an URI there, you just have to pass the domain name.
_hostname = "somehost.somedomain";
_httpsession_secure = new HTTPSClientSession(_hostname, _port);
I have a Java client, which obtains an autogenerated port. After starting the actor system, I want to access the port.
Config clientConfig = ConfigFactory.parseString("akka.remote.netty.tcp.port = 0")
.withFallback(ConfigFactory.parseString("akka.remote.netty.tcp.hostname = " + serverHostName))
.withFallback(ConfigFactory.load("common"));
actorSystem = ActorSystem.create("clientActorSystem", clientConfig);
// how to access the generated port here..!?
The port must already be set since the log output after ActorSystem.create(...) is like that:
[INFO] [03/31/2016 14:11:32.042] [main] [akka.remote.Remoting] Starting remoting
[INFO] [03/31/2016 14:11:32.233] [main] [akka.remote.Remoting] Remoting started; listening on addresses :[akka.tcp://actorSystem#localhost:58735]
[INFO] [03/31/2016 14:11:32.234] [main] [akka.remote.Remoting] Remoting now listens on addresses: [akka.tcp://actorSystem#localhost:58735]
If I try to get it via the configuration with actorSystem.settings().config().getValue("akka.remote.netty.tcp.port"), I still get 0 as defined before.
Has anyone an idea how this port (58735 in the example) can be accessed?
Using scala you can get Option of port on which Actor system is currently running:
val port = system.provider.getDefaultAddress.port
Hope you will be able to get the same code in Java.
The accepted answer probably worked for older versions of Akka but as of now (version 2.5.x) you will be getting something like:
Error:(22, 18) method provider in trait ActorRefFactory cannot be accessed in akka.actor.ActorSystem
The solution would be to use akka extensions. Here is how I use it:
Example. scala
package example
import akka.actor._
class AddressExtension(system: ExtendedActorSystem) extends Extension {
val address: Address = system.provider.getDefaultAddress
}
object AddressExtension extends ExtensionId[AddressExtension] {
def createExtension(system: ExtendedActorSystem): AddressExtension = new AddressExtension(system)
def hostOf(system: ActorSystem): String = AddressExtension(system).address.host.getOrElse("")
def portOf(system: ActorSystem): Int = AddressExtension(system).address.port.getOrElse(0)
}
object Main extends App {
val system = ActorSystem("Main")
println(AddressExtension.portOf(system))
}
I could setup KIE Execution Server (6.3.0.Final) and Workbench (6.3.0.Final) on Wildfly 8.1.0.Final using information available in blog:
http://mswiderski.blogspot.in/2015/10/installing-kie-server-and-workbench-on.html
Both server and Workbench are working fine and Server is visible in Workbench under "Server Management Browser" tab.
My next step is to deploy a simple container on server and test REST GET and POST calls, hence I followed steps mentioned in Question: HelloWorld using Drools Workbench & KIE Server
The only change in Java and DRL code is with respect to package. Below is my Java code:
package test.myproject;
/**
* This class was automatically generated by the data modeler tool.
*/
public class HelloWorld implements java.io.Serializable
{
static final long serialVersionUID = 1L;
private java.lang.String message;
public HelloWorld()
{
}
public java.lang.String getMessage()
{
return this.message;
}
public void setMessage(java.lang.String message)
{
this.message = message;
}
public HelloWorld(java.lang.String message)
{
this.message = message;
}
}
DRL file code:
package test.myproject;
import test.myproject.HelloWorld;
rule "hello"
when
HelloWorld(message == "Joe");
then
System.out.println("Hello Joe!");
end
The code is built successfully and deployed as container on the server. A GET Query using RESTClient/PostMan/Advanced REST Client gives proper response.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<response type="SUCCESS" msg="Info for container myproject">
<kie-container container-id="myproject" status="STARTED">
<release-id>
<artifact-id>MyProject</artifact-id>
<group-id>test</group-id>
<version>1.0</version>
</release-id>
<resolved-release-id>
<artifact-id>MyProject</artifact-id>
<group-id>test</group-id>
<version>1.0</version>
</resolved-release-id>
<scanner status="DISPOSED"/>
</kie-container>
</response>
However When I POST to container with below content:
<batch-execution lookup="defaultKieSession">
<insert out-identifier="message" return-object="true" entrypoint="DEFAULT">
<test.myproject.HelloWorld>
<message>Joe</message>
</test.myproject.HelloWorld>
</insert>
Note that I did make changes to XML as per change in code. I did try with different options like etc, but I get response as :
Status Code: 405 Method Not Allowed
Allow: HEAD, DELETE, GET, OPTIONS, PUT
Cache-Control: no-cache, no-store, must-revalidate
Connection: keep-alive
Content-Length: 0
Date: Thu, 10 Dec 2015 05:29:09 GMT
Expires: 0
Pragma: no-cache
Server: WildFly/8
X-Powered-By: Undertow/1
Looks like POST option is not allowed, Hence tried PUT but got response as:
Status Code: 415 Unsupported Media Type
Cache-Control: no-cache, no-store, must-revalidate
Connection: keep-alive
Content-Length: 0
Date: Thu, 10 Dec 2015 05:32:17 GMT
Expires: 0
Pragma: no-cache
Server: WildFly/8
X-Powered-By: Undertow/1
Can anyone tell me where I am going wrong. I also checked log file and see below error when POST is called:
2015-12-10 10:59:09,208 WARN [org.jboss.resteasy.core.ExceptionHandler] (default task-48) failed to execute: javax.ws.rs.NotAllowedException: No resource method found for POST, return 405 with Allow header
at org.jboss.resteasy.core.registry.SegmentNode.match(SegmentNode.java:375) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.registry.SegmentNode.match(SegmentNode.java:114) [resteasy-jaxrs-3.0.8.Final.jar:]
and error when PUT is called:
2015-12-10 11:02:17,127 WARN [org.jboss.resteasy.core.ExceptionHandler] (default task-50) failed to execute: javax.ws.rs.NotSupportedException: Cannot consume content type
at org.jboss.resteasy.core.registry.SegmentNode.match(SegmentNode.java:380) [resteasy-jaxrs-3.0.8.Final.jar:]
at org.jboss.resteasy.core.registry.SegmentNode.match(SegmentNode.java:114) [resteasy-jaxrs-3.0.8.Final.jar:]
It is working now. Changes needed are as follows:
URL to call during POST is : http://localhost:8080/kie-server/services/rest/server/containers/instances/myproject
From 6.3.0 onward instances needs to be used (Make note of it :))
KIE Server in 6.3.0 supports JAXB, JSON and Xstream. Since default is JAXB you would need to provide JAXB valid content. Alternatively you could set HTTP header to inform KIE Server to use Xstream as marshaller:
Header name: X-KIE-ContentType
Header Value XSTREAM
Hence set proper header
Finally XML should be in the form:
<batch-execution lookup="defaultKieSession">
<insert out-identifier="test">
<test.myproject.HelloWorld>
<message>"Joe"</message>
</test.myproject.HelloWorld>
</insert>
<fire-all-rules/>
<get-objects out-identifier="test"/>
</batch-execution>
Watch out the output "Hello Joe!" in command prompt.
Thanks to Maciej Swiderski for all the support
I'm using the following project for enabling APNS in my project:
https://github.com/stephenmuss/django-ios-notifications
I'm able to send and receive push notifications on my production app fine, but the sandbox apns is having strange issues which i'm not able to solve. It's constantly not connecting to the push service. When I do manually the _connect() on the APNService or FeedbackService classes, I get the following error:
File "/Users/MyUser/git/prod/django/ios_notifications/models.py", line 56, in _connect
self.connection.do_handshake()
Error: [('SSL routines', 'SSL3_READ_BYTES', 'sslv3 alert handshake failure')]
I tried recreating the APN certificate a number of times and constantly get the same error. Is there anything else i'm missing?
I'm using the endpoints gateway.push.apple.com and gateway.sandbox.push.apple.com for connecting to the service. Is there anything else I should look into for this? I have read the following:
Apns php error "Failed to connect to APNS: 110 Connection timed out."
Converting PKCS#12 certificate into PEM using OpenSSL
Error Using PHP for iPhone APNS
Turns out Apple changed ssl context from SSL3 to TLSv1 in development. They will do this in Production eventually (not sure when). The following link shows my pull request which was accepted into the above project:
https://github.com/stephenmuss/django-ios-notifications/commit/879d589c032b935ab2921b099fd3286440bc174e
Basically, use OpenSSL.SSL.TLSv1_METHOD if you're using python or something similar in other languages.
Although OpenSSL.SSL.SSLv3_METHOD works in production, it may not work in the near future. OpenSSL.SSL.TLSv1_METHOD works in production and development.
UPDATE
Apple will remove SSL 3.0 support in production on October 29th, 2014 due to the poodle flaw.
https://developer.apple.com/news/?id=10222014a
I have worked on APN using python-django, for this you need three things URL, PORT and Certificate provided by Apple for authentication.
views.py
import socket, ssl, json, struct
theCertfile = '/tmp/abc.cert' ## absolute path where certificate file is placed.
ios_url = 'gateway.push.apple.com'
ios_port = 2195
deviceToken = '3234t54tgwg34g' ## ios device token to which you want to send notification
def ios_push(msg, theCertfile, ios_url, ios_port, deviceToken):
thePayLoad = {
'aps': {
'alert':msg,
'sound':'default',
'badge':0,
},
}
theHost = ( ios_url, ios_port )
data = json.dumps( thePayLoad )
deviceToken = deviceToken.replace(' ','')
byteToken = deviceToken.decode('hex') # Python 2
theFormat = '!BH32sH%ds' % len(data)
theNotification = struct.pack( theFormat, 0, 32, byteToken, len(data), data )
# Create our connection using the certfile saved locally
ssl_sock = ssl.wrap_socket( socket.socket( socket.AF_INET, socket.SOCK_STREAM ), certfile = theCertfile )
ssl_sock.connect( theHost )
# Write out our data
ssl_sock.write( theNotification )
# Close the connection -- apple would prefer that we keep
# a connection open and push data as needed.
ssl_sock.close()
Hopefully this would work for you.