Kong / insomnia

The open-source, cross-platform API client for GraphQL, REST, WebSockets, SSE and gRPC. With Cloud, Local and Git storage.
https://insomnia.rest
Apache License 2.0
34.44k stars 1.94k forks source link

[Question] Websocket Support? #528

Closed Lizhooh closed 2 years ago

Lizhooh commented 6 years ago

Is insomnia likely to support websocket?

sibbl commented 6 years ago

That would be a killer feature, if opening Websockets, reading the stream and sending messages through the UI would be possible.

gschier commented 6 years ago

To be honest, I currently have no plans to support websockets, but I also don't work with them so don't understand how the workflow would be different from regular HTTP requests. I'm also not sure if libcurl supports websockets, which is what Insomnia uses to send requests.

Are there any awesome websocket debugging tools out there? I would love to be enlightened both about existing tools and what your ideal workflow would look like.

Lizhooh commented 6 years ago

Hi gschier. I hope to have a tool that makes it easy to debug websocket server/clinet. I've seen a debugging tool for websocket, but it can only debug socket.io.You can look at this tool: socket.io-tester.

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

ZigMeowNyan commented 6 years ago

Probably one of the major differences would be that websocket, like most messaging protocols, isn't required to be designed around the request/response paradigm. Websockets can stream events, and messages either way might not elicit responses. The connections are much more likely to persist beyond the length of the request.

So you'd probably want some type of persistent connection management. Either with predefined endpoints that you could reference, or with endpoint templates. Honestly, I'd love a few more dimensions in the configuration templating anyway. There are times when I want to flip more switches and turn more knobs than the base and sub-environments allow for. Sub-environments really only let you change one set of values, so you end up with more sub-environments than necessary, or you end up manually changing some values in different environments.

For request/response messages, the interface could be very similar to what it is now. If you're sending your messages slowly and synchronously, it'll work fine. But it's probably not a bad idea to consider an additional websocket data pane that streams the messages as they come in. It'd be handy for things like event subscriptions, Maybe you could check the URI for the ws:// and wss:// (secure) schemes and switch behavior based on that.

With Websocket, you can send several messages at once and be waiting for responses to all of them. Generally users who need to directly relate responses to the original requests over websocket, they'll have some means of doing so in the message itself. For structured messages like JSON and XML, you'd add a property that matches one provided in the request. This could be pretty tricky to implement, as you might need two filters: one for the request and one for the response to pair them. Websockets can also send strings and binary data, which could require more complex logic to parse the messages. For complex binary messages (e.g. protobuf), you might need plugins that understand the logic and can load the definition files. But honestly, just JSON/XML/string support would be a huge step forward. Binary support is a much lower priority, And initial implementations could leave all parsing to the user.

Once you've got a basic configuration interface for event streaming, people could look into adding alternate messaging implementations like socket.io, SignalR or STOMP. Binary message support and protocol definitions (e.g. .proto files) could be another thing to start working into plugins (e.g. gRPC, but implemented over HTTP).

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

taybin commented 6 years ago

Can we reopen this? It's still a valid request.

LukeBousfield commented 6 years ago

I agree. I think this would be a great idea, and would really help with my testing.

LukeBousfield commented 6 years ago

+1

oleg-korolenko commented 6 years ago

+1

demidovsky commented 6 years ago

+1

isubasti commented 6 years ago

+1

odwrotnie commented 6 years ago

+1

plashenkov commented 6 years ago

+1

drsect0r commented 6 years ago

+1

ignat-piskunov commented 6 years ago

+1

Albert221 commented 6 years ago

+1

nbw commented 6 years ago

+1

odwrotnie commented 6 years ago

+1

gschier commented 6 years ago

Please refrain from leaving +1 comments as they are not very helpful. I would much rather you leave more detailed comments on potential UI, UX, technical, implementation, etc.

Thanks! ❤️

ZigMeowNyan commented 6 years ago

People are leaving +1s because the stale bot keeps wanting to deprecate the issue and everyone's really interested in the feature. If it wasn't at risk of being closed, you'd probably have a lot less drive-by +1s.

Also, Lizhooh and I provided some feedback at the end of last year/beginning of this one, but we got no response or acknowledgement of it. And, to add to the feedback, apparently curl does support some basic WS functionality if you set the headers properly to upgrade the connection from HTTP to WS. I'd imagine that might also be available in libcurl, but there's also other libraries available that can provide better interfaces when working with websockets. If libcurl isn't going to cut it, than maybe it's worth investigating/documenting a generic interface for requests/responses so other people can implement it with different libraries while not breaking too many things. That way you can pave the way for others to implement this. As it stands, it's probably too invasive for others to attempt it as it might not get merged after completion.

If you're not interested in implementing the feature personally, that's fair. But letting it auto-close as stale doesn't seem to be the right approach, as it's a known feature that's very popular and in-demand. Plus, if you close it, people are just going to pop in and add new issues on the same topic. Have you considered adding an "Up for grabs" label indicating that others are free to implement it and telling the stale bot to leave issues with those tags alone?

gschier commented 6 years ago

Thanks for the reply @ZigMeowNyan!

I thought the "Needs Discussion" tag what on the @stalebot list but I noticed it was marked "Stale" after that tag was applied. I just added it to the config so it shouldn't be closed again. Also, sorry for not responding to your previous message. I did read it at the time but never had the cycles to write a response.

I've taken more than a few opportunities since my last reply to consider adding websocket support, so here's where I stand currently.

Partial Support

If we can come up with a way to get a streaming data connection using libcurl then I would consider updating the response viewer to support realtime updates from a websocket connection. Response streaming should probably be implemented anyway, since HTTP responses can come in chunks.

Full Support

Adding complete websocket support is a much different story.

The difference between websockets and regular HTTP (as you said) is that they don't follow the request/response paradigm. Connections are persistent and there can be multiple push/pull events on the same "request." This means that major changes would need to be made to Insomnia's core backend and UI/UX. Because of the ongoing maintenance required for such a large change, I would rather not support them at all than to support them poorly.


So the real question is.. is the benefit worth the effort required?

For Partial Support? I would say "yes" if can be implemented with the current network stack (libcurl) and the demand continues to increase.

For Full Support? I would love to say yes but unfortunately the numbers don't add up. This issue only has ~30 votes and I don't have many people requesting it on non-GitHub channels either. There's a reason there any good apps for debugging websockets. The market is just to small and fragmented at this point in time.

I'll leave it at that for now. I'm sorry if I sounded negative, but I want to provide my honest opinion so we're all on the same page.

ZigMeowNyan commented 6 years ago

Thanks for responding. It's nice to hear back on the issue at all, as I know you're not enthusiastic about it.

If we can come up with a way to get a streaming data connection using libcurl then I would consider updating the response viewer to support realtime updates from a websocket connection. Response streaming should probably be implemented anyway, since HTTP responses can come in chunks.

I'm not great with using libcurl, but from what I can see, they've implemented protocol switching. Which gives partial support for the connection establishment (e.g. when upgrading from HTTP) out of the box. Googling brought me to the GPL-based MegucoData repository for a C++ implementation of an HTTP-upgraded websocket client using curl_easy. So it's possible. And on the curl samples page there's one about using external sockets, which could work for direct websocket establishment. As websocket connections may be upgraded, but some servers will only want direct websocket connection (not HTTP).

I still think it might be better to start by defining a plugin interface for connection management and messaging. Libcurl seems capable of websocket if you're willing to get dirty, but there are other libraries that would be more straight-forward about it. Plus, it opens the doors for people writing new transports that could extend the utility of insomnia outside of vanilla HTTP.

Partial support

Even though the websocket protocol itself isn't based around the request/response paradigm, the bit that would fit into Insomnia most likely would be. Yes, the websocket can be shared for multiple messages, but you don't really have an interface for sending multiple requests, so it'd still be the server responding to one message at a time. The most likely scenarios that wouldn't really fit for this are:

  1. message chaining - chaining multiple request/response pairs based on the results of a prior request/response. This could also theoretically exist for HTTP APIs, but isn't really supported by the current templating system anyway.
  2. event subscriptions - notifying the server that you'd like to receive events which could stream in over a period of time. From an Insomnia standpoint, the first implementation could be as simple as providing a an activity timeout (configured per ws request) for the connection to remain open and listening for new messages after the initial response.

I would love to say yes but unfortunately the numbers don't add up. This issue only has ~50 votes and I don't have many people requesting it on non-GitHub channels either. There's a reason there any good apps for debugging websockets. The market is just to small and fragmented at this point in time.

I think the interest is much higher than indicated. You did state back in Oct 2017 that support wasn't planned for Websocket, so many of those interested might have already moved on. Those of us hanging out in this issue are just the stubborn ones, honestly. A lot of people working with websockets are just used to the existing workflow or found other means. Like how I wrote an HTTP bridge for testing ours which funnels the messages using POST data. Websocket has been a big thing for a while. People are just used to bad tools with it and don't know that it can be better.

But I also don't think this needs to start by immediately redesigning things for realtime. Even just supporting basic request/response handling for websocket takes care of a lot of use cases. Especially if there's some logic for maintaining the connection open for a bit so the user can send some canned requests themselves in sequence.

Thanks again for listening!

ph55 commented 6 years ago

GraphQL subscriptions also require WS

TheAifam5 commented 5 years ago

You can use websocket with libcurl using CURLOPT_OPENSOCKETFUNCTION and CURLOPT_WRITEFUNCTION

gschier commented 5 years ago

Woah, didn't know about OPENSOCKETFUNCTION. Here's some more info https://curl.haxx.se/libcurl/c/CURLOPT_OPENSOCKETFUNCTION.html

I don't have time to play with it but if someone wants to put together a small proof-of-concept showing very basic functionality, that'd be useful for getting the conversation going.

tostringtheory commented 5 years ago

@gschier - I'll be honest that this is a feature I've long looked for and would love to see a tool support. I want to give it some thought but I might have some ideas on attacking this one for a PR, but if so it would probably end up after the holiday season. Do you have any thoughts/concerns before I look into it further?

gschier commented 5 years ago

@tostringtheory my main concern is that we don't go too far with it at first. I think if you can get a minimal amount of code (less than 100 lines or so) that demonstrates the ability to connect to a websocket and push/pull data, we can discuss next steps from there.

Also, we should try to stick to using the libcurl functionality for this as much as possible.

tostringtheory commented 5 years ago

@gschier - Yeah, I definitely wouldn't try and implement the full feature before doing a PR to show implementation of this magnitude. I'm still working through it in my head, so not 100% sure on it yet. I would agree that we'd want to stick with libcurl too, and not introduce more complexity than necessary.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

toughengineer commented 5 years ago

Hey all! I use Insomnia almost daily and I really really miss websocket support in any form. My scenario is just sending requests to the backend and watching what it spits out, all in JSON.

Currently I use WebSocket Test Client and it works... but it is super ugly and not productive. Also I learned to use Network debugging tab in Chrome and would like message inspection to look something similar to that.

But for the start I would be happy to have support for websocket in any form. I'm willing to develop whatever is needed if it is in C++. So what's the next step?

By the way, as far as I understand Chromium (and Electron) support websocket out of the box right in JavaScript. Even using that (without using libcurl) would be enough for the start. Otherwise there is a websocket node.js lib here: https://github.com/websockets/ws

sebmor commented 5 years ago

Being able to test websockets inside insomnia would still be a great feature. Hope this gets reconsidered at some point so I want to voice my support.

htrgouvea commented 5 years ago

I'm coming to the discussion now, but anyway: I'd love to see this feature!

Lizhooh commented 5 years ago

This is the function I envision (very small):

  1. You can set the url to connect to the websocket server.
  2. Send a message to the server to listen for the returned message.
  3. View the details of each message.

Simple UI:

20190811161419

Extarys commented 5 years ago

Anti Stale Bot comment.

jayarjo commented 5 years ago

@Lizhooh wouldn't it be better if json messages are generated, instead of having them to be entered manually.

cgladue commented 4 years ago

Would also love to have any support for WS included in Insomnia

SergioSuarezDev commented 4 years ago

+1000

DrYSG commented 4 years ago

I also am trying to test out graphql subscriptions, and need a websocket client.

artoodeeto commented 4 years ago

found this one. https://www.websocket.org/echo.html this might help if you really want to test ws connections

DrYSG commented 4 years ago

No help for me, the GraphQL server is not on the internet.

Sent with GitHawk

Besides if I did want something to test internet sites, I would use https://postwoman.io/graphql which has a beautiful interface. (reminds me of insomnia).

jcelliott commented 4 years ago

I would also like to have support for GraphQL subscriptions (I realize that entails more than just websocket support, but the only other issue I found for it was closed). The other options for testing subscriptions aren't great right now. Postman also has GraphQL support, but supporting subscriptions would be a great way to differentiate Insomnia.

DrYSG commented 4 years ago

Postwoman claims subscribe support. But it is internet only.

Sent with GitHawk

artificial-cassiano commented 4 years ago

any idea about the timeline for the release of WebSockets support on Insomnia? (ps: I like this tool a lot! great job building it).

toughengineer commented 4 years ago

I actually implemented my own (shitty and ugly) one-page WebSocket client for the application I'm testing (using stackoverflow, MDN, W3Schools, etc.), though with blackjack, and hookers! 😁 Still have no idea how to do it within a Node app.

Here is the gist of it... ```javascript ws = new WebSocket(url); ws.onopen = () => { console.log('Opened web socket'); connectionStatus.className = 'connected'; connectButton.style.display = 'none'; closeButton.style.display = ''; this.setMessageEditEnabled(true); connectButton.removeAttribute('disabled'); for (const e of this.elementsToUndisable) e.removeAttribute('disabled'); connected = true; commands = null; removeChildren(commandList); document.getElementById('messageFormSection').style.display = 'none'; this.onMessage = this.onMessageWaitCommandDescriptions; ws.send('{"some":{"initial":"request"}}'); }; ws.onclose = (e) => { console.log('Closed web socket'); ws = null; connected = false; connectButton.style.display = ''; closeButton.style.display = 'none'; wsUrl.removeAttribute('disabled'); connectionStatus.className = 'disconnected'; this.setMessageEditEnabled(false); for (const e of this.elementsToUndisable) e.setAttribute('disabled', ''); }; ws.onmessage = (event) => { this.onMessage(event); }; ws.onerror = (event) => { console.log('Failed to connect to web socket'); connectButton.removeAttribute('disabled'); }; ```

Not rocket science at all.

toughengineer commented 4 years ago

OK, I decided that my shitty one-page WS client is polished enough (ha!) to share, with the hope it is useful for someone. ws-client.zip

I hope you can figure it out.

As neat features there are indication of timestamps for messages, and calculation of time differences to previous and selected messages (hover messages to see the popup):

messages

you can send selected message by clicking Send selected button;

selected JSON message is shown as a tree on the right, you can search the tree with RegEx; hold Control (Command on macos(?)) and click + to expand or to collapse the whole branch; you can copy branches by clicking the appearing 📋 button;

it is written so that on connection we ask for the command descriptions:

  ws.onopen = () => {
    console.log('Opened web socket');
    //...
    this.onMessage = this.onMessageWaitCommandDescriptions;
    ws.send('{"request":"command_descriptions"}');
  };
//...
onMessage: null,
onMessageWaitCommandDescriptions: function (event) {
  const timestamp = Date.now();
  if (event.data.lastIndexOf('{"request":"command_descriptions"}') != -1) {
    try {
      var response = JSON.parse(event.data);
      this.commands = response.payload;
      setCommands(commandList, this.commands);
      this.onMessage = function (event) {
        this.addMessage(event.data, 'in', Date.now());
      };
      return;
    }
    catch (e) {
      console.log(e.message);
    }
  }
  this.addMessage(event.data, 'in', timestamp);
},

upon receiving the descriptions, commands appear on the left and show a form when clicked:

commands

you can use the form to send requests or copy the resulting message to the editor by clicking Copy to editor button.

If you don't want this functionality, just replace this.onMessage initialization in ws.onopen handler like this:

  ws.onopen = () => {
    console.log('Opened web socket');
    //...
    this.onMessage = function (event) {
      this.addMessage(event.data, 'in', Date.now());
    };
    ws.send('{"request":"command_descriptions"}');
  };
Uncomment the dummy command description and messages to check out how it works. (click to expand) //WSClient.commands = [ // { // name: 'test_request', // parameters: { // 'a boolean': { // 'type': 'boolean', // 'is required': false // }, // 'an integer': { // 'type': 'integer', // 'is required': true // }, // 'the number': { // 'type': 'number', // 'is required': false // }, // 'a string': { // 'type': 'string', // 'is required': true // }, // 'an object': { // 'type': 'object', // 'is required': false // } // } // } //]; //setCommands(commandList, WSClient.commands); //WSClient.addMessage('{"test":{"value":42,"subobject":{"value":"foobar"}}}', 'in', Date.now()); //WSClient.addMessage('{"test2":"bleh!"}', 'out', Date.now()); //WSClient.addMessage('invalid JSON', 'in', Date.now());

I'm really happy with it for the purposes of testing the app I'm working on, though I wish it is implemented in insomnia with all these features. Anything less than in this prototype will not be appealing to me anymore.

Hope it's useful for someone. Please tell if it's not working for you, though don't expect immediate reply.

Also feel free to use the code however you want.

migolovanov commented 3 years ago

Also would like to see this feature in Insomnia, and in case it would help anyone - the best websocket client I've found so far is chrome extension WebSocket King Client

JCMais commented 3 years ago

node-libcurl author here. I just added an example showing how to build a WebSockets client using the library: https://github.com/JCMais/node-libcurl/blob/develop/examples/21-websockets-client.js

It's very barebones but should work as inspiration if this feature is to be implemented using node-libcurl itself.

develohpanda commented 3 years ago

node-libcurl author here. I just added an example showing how to build a WebSockets client using the library: JCMais/node-libcurl@f3edcfb/examples/21-websockets-client.js

It's very barebones but should work as inspiration if this feature is to be implemented using node-libcurl itself.

Wow, that's awesome! There has not been much investigation into how WS support might be implemented yet, so this will be very useful when the time comes.

In terms of UI, the gRPC feature-set (next in the pipeline) should provide many of the assets required for Websockets as well.

Matz92 commented 3 years ago

@JCMais that would be great! I love Insomnia and i hope this feature will be added soon