Giter Club home page Giter Club logo

smoke's People

Contributors

chrisdinn avatar davidharcombe avatar ghouet avatar gramk avatar jasongoodwin avatar paintcan avatar sanatapal avatar vikraman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smoke's Issues

URL parsing error not handled correctly

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]

HashedWheelTimer warning

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.

OutOfMemoryException upon sending a huge files.

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.

Parsing multipart/form-data from request body

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.

Allow access log to print user agent and other standard fields

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"

Closing the server without terminating the process.

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.

Problem with multiple 'Set-Cookie' header

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.