mdialog / smoke Goto Github PK
View Code? Open in Web Editor NEWSimple, asynchronous HTTP using Scala.
License: Other
Simple, asynchronous HTTP using Scala.
License: Other
In 2.11.0 DelayedInit has been deprecated. Smoke should avoid using it in the future.
More discussion here:
Malformed URLs through an exception in a manner that''s inappropriate. It happens so early in the request flow that the request isn't even seen by the application.
java.lang.IllegalArgumentException: URLDecoder: Incomplete trailing escape (%) pattern
at java.net.URLDecoder.decode(URLDecoder.java:187) ~[na:1.7.0_67]
at smoke.Request$class.decode(Request.scala:93) ~[smoke_2.10-2.1.0.jar:2.1.0]
at smoke.netty.NettyRequest.decode(NettyRequest.scala:22) ~[smoke_2.10-2.1.0.jar:2.1.0]
at smoke.Request$$anonfun$parseParams$2.apply(Request.scala:88) ~[smoke_2.10-2.1.0.jar:2.1.0]
at smoke.Request$$anonfun$parseParams$2.apply(Request.scala:87) ~[smoke_2.10-2.1.0.jar:2.1.0]
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) ~[scala-library-2.10.4.jar:na]
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) ~[scala-library-2.10.4.jar:na]
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33) ~[scala-library-2.10.4.jar:na]
at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:108) ~[scala-library-2.10.4.jar:na]
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244) ~[scala-library-2.10.4.jar:na]
at scala.collection.mutable.ArrayOps$ofRef.map(ArrayOps.scala:108) ~[scala-library-2.10.4.jar:na]
at smoke.Request$class.parseParams(Request.scala:87) ~[smoke_2.10-2.1.0.jar:2.1.0]
at smoke.netty.NettyRequest.parseParams(NettyRequest.scala:22) ~[smoke_2.10-2.1.0.jar:2.1.0]
at smoke.Request$class.formParams(Request.scala:46) ~[smoke_2.10-2.1.0.jar:2.1.0]
at smoke.netty.NettyRequest.formParams$lzycompute(NettyRequest.scala:22) ~[smoke_2.10-2.1.0.jar:2.1.0]
at smoke.netty.NettyRequest.formParams(NettyRequest.scala:22) ~[smoke_2.10-2.1.0.jar:2.1.0]
at smoke.Request$class.params(Request.scala:50) ~[smoke_2.10-2.1.0.jar:2.1.0]
at smoke.netty.NettyRequest.params$lzycompute(NettyRequest.scala:22) ~[smoke_2.10-2.1.0.jar:2.1.0]
at smoke.netty.NettyRequest.params(NettyRequest.scala:22) ~[smoke_2.10-2.1.0.jar:2.1.0]
at com.mdialog.odsm.StreamsApi.authenticate(StreamsApi.scala:33) ~[on_demand_stream_manager-5.8.0.jar:na]
at com.mdialog.odsm.StreamsApi$$anonfun$handleRequest$1.apply(StreamsApi.scala:86) ~[on_demand_stream_manager-5.8.0.jar:na]
at com.mdialog.odsm.StreamsApi$$anonfun$handleRequest$1.apply(StreamsApi.scala:86) ~[on_demand_stream_manager-5.8.0.jar:na]
at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) ~[scala-library-2.10.4.jar:na]
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) ~[scala-library-2.10.4.jar:na]
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41) [akka-actor_2.10-2.3.4.jar:na]
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393) [akka-actor_2.10-2.3.4.jar:na]
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [scala-library-2.10.4.jar:na]
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [scala-library-2.10.4.jar:na]
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [scala-library-2.10.4.jar:na]
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [scala-library-2.10.4.jar:na]
I get this warning:
[2013-08-12 21:55:58,027][WARN ][netty.util.internal.SharedResourceMisuseDetector] You are creating too many HashedWheelTimer instances. HashedWheelTimer is a shared resource that must be reused across the application, so that only a few instances are created.
I have a pool of nested actors which reuse the smoke ActorSystem
, and I'm using akka 2.2
.
Apart from the way used in examples, I have tried several other ways to send big files using smoke server but there is no way to do it correctly.
This is probably because when sending the raw data, the function only accepts an array and not a stream.
I was trying to parse request body to multipart/form-data using org.apache.commons.fileupload
. For that I needed request content as Array[Byte]
. I first used getBytes("UTF-8")
on body. This worked fine with text files, but for binary files, this didn't seem to work. On further examination, I noticed that the hex for new file was shifted by some amount.
As a workaround, I changed the type of body to Array[Byte]
and made these changes in netty/NettyRequest.scala:
val contentLength = nettyRequest.getContent.readableBytes
var byteArray = new Array[Byte](contentLength)
nettyRequest.getContent.readBytes(byteArray)
val body = byteArray
This seemed to work fine with any type of file.
We should emphasize the importance of updating the session secret.
It's common to have user agent in the access log. Would help with troubleshooting issues if the access log can be customized similar to apache.
127.0.0.1 - - [05/Feb/2012:17:11:55 +0000] "GET / HTTP/1.1" 200 140 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.5 Safari/535.19"
So far I haven't found a way to close the server without closing the entire process.
If the server is created using the object of a class by extending to Smoke and not SmokeApp, then shouldn't there be a method to shutdown the server if needed.
With current implementation of headers as a Map
, we face a problem that we cannot have same key repeated multiple times. But according to RFC-6265 (Look for "multiple Set-Cookie header"), we can set multiple cookies (specifically, those with different attributes for Path/Secure/Httponly) by having multiple Set-Cookie
header.
Problem code (Derived from ActorExampleApp.scala):
package smoke.examples
import smoke._
import akka.actor._
import akka.pattern.ask
class Responder extends Actor {
def receive = {
case GET(Path("/example")) ⇒
Thread.sleep(1000)
sender ! Response(Ok, headers = Map ("Set-Cookie" -> "a=1;"), body = "It took me a second to build this response.\n")
case _ ⇒ sender ! Response(NotFound)
}
}
object ActorExampleApp extends Smoke {
val actor = system.actorOf(Props[Responder])
onRequest(actor ? _ mapTo manifest[Response])
after { response ⇒
val headers = response.headers + ("Server" -> "ActorExampleApp/0.0.1") + ("Set-Cookie" -> "b=2; HttpOnly")
Response(response.status, headers, response.body)
}
}
Expected output:
$ http localhost:7771/example --verbose
GET /example HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, compress
Host: localhost:7771
User-Agent: HTTPie/0.5.0
HTTP/1.1 200 OK
Connection: keep-alive
Content-Encoding: gzip
Content-Length: 68
Server: ActorExampleApp/0.0.1
Set-Cookie: a=1;
Set-Cookie: b=2; HttpOnly
It took me a second to build this response.
The problem inherently is because of use of Map
since that does not allow duplicate keys. List
seems to be a better structure, but appending to List
is O(n) operation, though prepending is O(1). Although relative ordering of http headers is should not matter according to RFC2616 (Look for "Multiple message-header"), it does matter in case of two Set-Cookie
, because, later one would get higher preference.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.