Giter Club home page Giter Club logo

websocket-scala-client's Introduction

Scala Websocket Client

build coverage mvn

Scala Websocket Client is an open-source library which provides a clean, programmer-friendly API to describe Websocket request/response machinery. Communication with server handled using one of the backends, which wrap other Scala or Java HTTP client implementations.

Supported backends:

  • Netty
  • JDK Http Client
  • Akka
  • Pekko
  • Zio-Http
  • Async-http-client
  • OkHttp
  • Armeria

Supported Serialization/Deserialization formats:

  • Avro using Avro4s
  • Protobuf
  • Json using Circe
  • Json using Play-Json
  • Json using Spray-Json
  • Json using Jsoniter-scala
  • Json using Borer
  • Json using uJson
  • CBOR using Borer

websocket-scala-client's People

Contributors

1van3 avatar andyglow avatar antonzherdev avatar charlesahunt avatar dcheckoway avatar lenstr avatar scala-steward avatar synesso 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

websocket-scala-client's Issues

Duplicate custom headers

A quick inspection in Wireshark revealed that the custom headers appeared twice in the request.

This sample code

val client = WebsocketClient(uri, protocolHandler, Map("test" -> "value"))
val ws = client.open()

produces the following request

GET / HTTP/1.1
upgrade: websocket
connection: upgrade
sec-websocket-key: [...]
host: [...]
sec-websocket-origin: [...]
sec-websocket-version: 13
test: value
test: value

Drop `akka` dependency

We use akka for testing purposes only
We might need to drop it and start using netty for test server too. Here is official example

Ping Support

Add support for sending a Ping frame MessageAdapter

Way to be notified that server has closed websocket

Hi,

We are using this library in order to test at acceptance level our websocket application.

We've tests like "if your are connected to the app through the websocket and don't send anything in 5 seconds, server will close the communication".

Is there a way to be notified through the WebsocketClient when server close the websocket or communication is broken?

Regards,
Sergi

Closing websocket client

Issue: calling cli.shutdown closes websocket incorrectly.

val cli = WebsocketClient(Uri(apiUrl), protocolHandler, headers)
val ws = cli.open()
// SOME CODE
cli.shutdown()

When cli.shutdown is called, I see following errors at server:

java.nio.channels.ClosedChannelException
        at org.jboss.netty.channel.socket.nio.AbstractNioWorker.cleanUpWriteBuffer(AbstractNioWorker.java:433)
        at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromUserCode(AbstractNioWorker.java:128)
        at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:99)
        at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:36)
        at org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendDownstream(DefaultChannelPipeline.java:779)
        at org.jboss.netty.channel.Channels.write(Channels.java:725)
        at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.doEncode(OneToOneEncoder.java:71)
        at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:59)
        at org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:591)
        at org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendDownstream(DefaultChannelPipeline.java:784)
        at org.jboss.netty.channel.SimpleChannelHandler.writeRequested(SimpleChannelHandler.java:292)
        at org.jboss.netty.channel.SimpleChannelHandler.handleDownstream(SimpleChannelHandler.java:254)
        at com.typesafe.netty.http.pipelining.HttpPipeliningHandler.handleDownstream(HttpPipeliningHandler.java:106)
        at org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:591)
        at org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:582)
        at org.jboss.netty.channel.Channels.write(Channels.java:704)
        at org.jboss.netty.channel.Channels.write(Channels.java:671)
        at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:348)
        at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$play$core$server$netty$PlayDefaultUpstreamHandler$$iteratee$1$1.apply(PlayDefaultUpstreamHandler.scala:298)
        at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$play$core$server$netty$PlayDefaultUpstreamHandler$$iteratee$1$1.apply(PlayDefaultUpstreamHandler.scala:291)
        at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$16$$anonfun$apply$17.apply(Iteratee.scala:544)
        at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$16$$anonfun$apply$17.apply(Iteratee.scala:544)
        at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)
        at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)
        at play.api.libs.iteratee.Execution$trampoline$.executeScheduled(Execution.scala:109)
        at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:71)
        at scala.concurrent.impl.Future$.apply(Future.scala:31)
        at scala.concurrent.Future$.apply(Future.scala:494)
        at play.api.libs.iteratee.RunQueue.execute(RunQueue.scala:122)
        at play.api.libs.iteratee.RunQueue.schedule(RunQueue.scala:115)
        at play.api.libs.iteratee.RunQueue.schedule(RunQueue.scala:66)
        at play.api.libs.iteratee.RunQueue.scheduleSimple(RunQueue.scala:88)
        at play.api.libs.iteratee.Concurrent$$anon$10$$anon$11.schedule(Concurrent.scala:459)
        at play.api.libs.iteratee.Concurrent$$anon$10$$anon$11.push(Concurrent.scala:484)
        at play.api.libs.iteratee.Concurrent$Channel$class.push(Concurrent.scala:50)
        at play.api.libs.iteratee.Concurrent$$anon$10$$anon$11.push(Concurrent.scala:456)
        at managers.DeviceActorWS$$anonfun$receive$3.applyOrElse(Relay2.scala:332)
        at akka.actor.Actor$class.aroundReceive(Actor.scala:482)
        at managers.DeviceActorWS.aroundReceive(Relay2.scala:224)
        at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
        at akka.actor.ActorCell.invoke(ActorCell.scala:495)
        at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
        at akka.dispatch.Mailbox.run(Mailbox.scala:224)
        at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
        at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
        at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
        at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

How can I disconnect websocket client gracefully so that I don't get such error stack at server side?
I am connecting this websocket client to play application.

OOM

You are not closing the channel. As a result - OutOfMemoryError if there are many WebSocketClient instances.

Add untyped Api

Research on if we can make a single websocket instance be used to pass both text and binary based frames

provide api + backend layers

  • Websocket Client API
    • netty based spi
    • akka based spi
    • pekko based spi
    • jdk9 httpclient based spi
    • AsyncHttpClient based client
    • okhttp based client

No Scala 2.12 release

It would be awesome to have it Scala 2.12 supporting.

Starting from 0.2.1 version there are no 2.12 artefacts ๐Ÿ˜’

Thanks!

Error when URI contains urlencoded params

As example you could use ws://sc.my.domain.com?type=stream&url=rtmp%3A%2F%2Ff1-perf-public.my.domain.com%2Fstatic%2F227ef79a-ec9b-4c67-b606-9816499bb0fa%3Fpassword%3Db9b59eb1-04e1-4c59-925a-d4261dcd7b1d
This happens because URI.getQuery returns unencoded value
You should user URI.getRawQuery

Add `websocket.ask` method

See if we can add a method similar to actor.?. Method that'd allow asynchronous request-response pattern

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.