Socket.io support for WSO2 API Manager Websocket? - websocket

Does inbuilt WebSocket API in WSO2 APIM manager supports socket.io/nodejs based endpoint?
I have socket.io based websocket server (in NodeJS) And socket.io javascript client, in between we are using WSO2 API manager for authenticating websocket connections. But WSO2 fails to connect backend server and gives nothing in response.
I used access_token query parameter for passing Bearer token (from JavaScript client) and it seems working as no error. But WSO2 does not forward requests to endpoint.
Same works fine with native WebSocket server-client.

You can add the following logs to <AM_HOME>/repository/conf/log4j.properties to debug the issue further.
For APIM 3.x.x you can change it according to the log4j2 and add to log4j2.properties
log4j.logger.org.wso2.carbon.inbound.endpoint.protocol.websocket.InboundWebsocketSourceHandler=DEBUG log4j.logger.org.wso2.carbon.inbound.endpoint.protocol.websocket.InboundWebsocketResponseSender=DEBUG
log4j.logger.org.wso2.carbon.websocket.transport.WebSocketClientHandler=DEBUG
log4j.logger.org.wso2.carbon.websocket.transport.WebsocketTransportSender=DEBUG

Previous answer was for socket.io JS client, here is the same hack for socket.io python client.
Modify client.py file from /home/user/.local/lib/python3.6/site-packages/engineio
line no. 515
change this,
return ('{scheme}://{netloc}/{path}/?{query}'
'{sep}transport={transport}&EIO=3').format(...
to this,
return ('{scheme}://{netloc}/{path}?{query}'
'{sep}transport={transport}&EIO=3').format(...
Now, instead of directly modifying actual flow we can use conditional parameter.
if self.noslash == 'true':
return ('{scheme}://{netloc}/{path}?{query}'
'{sep}transport={transport}&EIO=3').format(...
else return original statement.
noslash parameter can be fetched from connect() function in both engineio and socketio library of python.
def connect(self, url, headers={}, transports=None,
engineio_path='engine.io', noslash=None):
self.noslash = noslash
Here is the sample connection string for python-socketio
sio.connect('http://localhost:9099', headers={'Authorization':'Bearer 90e8sf10-3s1w-495f-b20d-5a009f63193v'}, transports=['websocket'], socketio_path='/livefeed/v1', noslash='true')

finally I get rid of this issue. Yes, WSO2 APIM websocket supports socket.io js library that will be the first answer to my own query. More on that, here are some findings.
The actual reason for issue was request URL pattern used by socket.io library and WSO2 APIM. Socket.io JS library make the final URL with / at the end of resource (reference), which is not accepted by query separation logic used by WSO2.
So in simple, this is acceptable
ws://localhost:9099/livefeed/v1?EIO=4&transport=websocket
but not this,
ws://localhost:9099/livefeed/v1/?EIO=4&transport=websocket
Solution:
After few discussions with WSO2 team, it was clear that it is impossible to implement changes at their end. So little hack in socket.io.js file worked for me.
line number - 2535
changed this,
_this.opts.path = _this.opts.path.replace(/\/$/, "") + "/";
to this,
if(typeof opts.noslash!== 'undefined' && opts.noslash== "true"){
_this.opts.path = _this.opts.path.replace(/\/$/, "");
}else{
_this.opts.path = _this.opts.path.replace(/\/$/, "") + "/";
}
and created socket using extra argument.
var socket = io.connect("http://localhost:9099?access_token=90e8sf10-3s1w-495f-b20d-5a009f63193v", { transports: ['websocket', 'polling'], path: '/livefeed/v1', noslash: 'true' });
I know this is not a actual solution, but it worked for me.

Related

laravel swift-mailer exception "Expected response code 250 but got an empty response" using gmail smtp-relay (database queue driver)

the gmail smtp-relay works fine using the sync driver, but if we queue the email we this error. cleared config, cache, & restarted queue workers. tested in prod and dev, same results
[2021-01-24 20:04:22] production.ERROR: Expected response code 250 but got an empty response {"exception":"[object] (Swift_TransportException(code: 0): Expected response code 250 but got an empty response at /home/****/****/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php:448)
were wondering is this because of serialization and something is not making it through that process???
using latest stable release of laravel >8.0. gmail smtp is authenticating just fine, per why the sync driver sends emails easily. maybe there needs to be a timeout on the queue jobs so they dont barrage gmail so quickly? also our code works fine using sendgrid for example as the smtp relay. thanks.
See https://laracasts.com/discuss/channels/laravel/laravel-swift-mailer-exception-expected-response-code-250-but-got-an-empty-response-using-gmail-smtp-relay-database-queue-driver
Update your AppServiceProvider.php
add this inside boot();
// Fix for SwiftMailer Service;
$_SERVER["SERVER_NAME"] = "your.domain.name";
For users of smtp-relay.gmail.com, if you use localhost/127.0.0.1 as domain during developments, you probably need to change the domain name to use in EHLO command to begin the transaction. I solved this by adding &local_domain=dev.mydomain.tld at the and of my DSN.
smtp://smtp-relay.gmail.com:587?encryption=tls&local_domain=dev.mydomain.tld&...
For SwiftMailer Symfony bundle (since 2.4.0), you can set the local_domain config parameter:
// config/packages/dev/swiftmailer.yaml
swiftmailer:
...
local_domain: dev.mydomain.tld
Explanation for the 2 previous Answers
if $_SERVER["SERVER_NAME"] is the solution:
When you are using cron
The reason is that $_SERVER["SERVER_NAME"] is null when cron is executed. $_SERVER["SERVER_NAME"] is usually only defined for http access.
Example implementation (laravel):
if (!isset($_SERVER['SERVER_NAME'])) {
$url = config('env.APP_URL');
$domain = mb_ereg_replace("http(s)? ://", "", $url);
$domainParts = explode('/', $domain);
ini_set('server_name', count($domainParts) > 0 ? $domainParts[0] : $domain)
}
References :
Cron Job $_SERVER issue
https://github.com/swiftmailer/swiftmailer/issues/992
if 'local_domain' is the solution
When you have a mailhost setting of MAIL_HOST=smtp-relay.gmail.com in your laravel project
The reason is that if local_domain' is not set, the protocol for mail communication with Gmail will be EHLO [127.0.0.1]` and the communication will be disconnected.
By the way, I used gmail->gmail alias and did not need relay in the first place, so I solved the problem by setting MAIL_HOST=smtp.gmail.com.
References:
https://blog.trippyboy.com/2021/laravel/laravel-expected-response-code-250-but-got-an-empty-response/
I had to deal with both of them because of cron messaging and MAIL_HOST=smtp-relay.gmail.com in my environment.
I hope this information will help you.

Cordova App 8.1 Caching HTTP request

I'm working on an app using Visual Studio 2015 Cordova tools on Windows 8.1. Target is also Windows 8.1.
The app is caching HTTP GET request. So the second GET request to the same resource returns a cached response. I have tested after disabling the network adapter and I still get a response with the cached results.
I am using jsforce libray to connect to salesforce.com. I know I can add a timestamp on the url but I would like to find fix not a work around.
Any ideas?
[UPDATE]
Issue is not related to jsforce as it works well on Android. The error is specific to Windows 8.1 and cordova.
As suggested in the question, timestamping the url helps: I used:
var url = "https://api.myurl.com/" + param1 + "?" + new Date().getTime()
I wrote a simple library to add caching to REST requests for Cordova: https://github.com/glauber-md/mobile-simple-web-call#using-this-library .
The library will use a local database (sqlite) to fetch server data and cache it locally where applicable (e.g. HTTP GET requests with cache-related headers).
Once it receives a 304 Response, it will use the cached data.
To send a GET request, you'd use:
wscall.get(
'http://myserver.org/users/1234',
// (Optional) query strings
null,
function(responseData) {
// Do something when the response is successful
},
function(error) {
// Do something when an error happens
}
);
Then the data would come from remote server or local cache depending of the HTTP server response.
Maybe it will help you.

Retrieving JSON from an external API with backbone

I'm new to backbone.js and I've read other solutions to similar problems but still can't get my example to work. I have a basic rails api that is returning some JSON from the url below and I am trying to access in through a backbone.js front end. Since they are one different servers I think I need to use a 'jsonp' request. I'm currently doing this by overriding the sync function in my backbone collection.
Api url:
http://guarded-wave-4073.herokuapp.com/api/v1/plans.json
sync: function(method, model, options) {
options.timeout = 10000;
options.dataType = 'jsonp';
options.url = 'http://guarded-wave-4073.herokuapp.com/api/v1/plans.json'
return Backbone.sync(method, model, options);
}
To test this I create a new 'plans' collection in my chrome console using "plans = new Plans()" and then "plans.fetch()" to try and get the JSON.
When I call plans.models afterwards I still have an empty array and the object that returns from plans.fetch() doesn't seem to have any json data included.
Any ideas where I'm going wrong?
I have had the same problem before. You should not have to override your sync method.
Taken from Stackoverflow Answer
"The JSONP technique uses a completely different mechanism for issuing HTTP requests to a server and acting on the response. It requires cooperating code in the client page and on the server. The server must have a URL that responds to HTTP "GET" requests with a block of JSON wrapped in a function call. Thus, you can't just do JSONP transactions to any old server; it must be a server that explicitly provides the functionality."
Are you sure your server abides to the above? Test with another compatible jsonp service (Twitter) to see if you receive results?
Have you tried overriding the fetch method as well?
You should add ?callback=? to your api url in order to enable jsonp

Settingup Proxy with htmlunit

I am new on htmlunit, and with almost No knowledge of programming.
In Centos - Webserver (for www.mydomain.com), i am trying to create a proxy.
I want my server to be used as proxy on request comming for www.mydomain.com and
send response as htmlsnapshot.
i saw some of the things like
SocketAddress addr = new InetSocketAddress("xxx.xxx.xx.xxx", 8888);
Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); //or Proxy.Type.SOCKS
URL url = new URL("http://mydomain.com/test"); URConnection conn =
url.openConnection(proxy);
But i wonder where to setup that.
Can this be done entirely from apache..
i dont see any configuration file as such fo htmlunit.
BTW, i have installed htmlunit ( using jpackage repo)
HTMLUnit is GUI-Less browser for Java programs Where did you see the code that you have included. From memory I cannot recall the API even having a Proxy Class. You can certainly point the WebClient at a proxy by passing in a ProxyConfig; and that is only there to declutter the WebClient Class.
Are you looking for a Proxy server, or a way to simulate a browser?

django ajax proxy view

A django web app needs to make ajax calls to an external url. In development I serve directly from django so I have a cross domain problem. What is the django way to write a proxy for the ajax call?
Here's a dead simple proxy implementation for Django.
from django.http import HttpResponse
import mimetypes
import urllib2
def proxy_to(request, path, target_url):
url = '%s%s' % (target_url, path)
if request.META.has_key('QUERY_STRING'):
url += '?' + request.META['QUERY_STRING']
try:
proxied_request = urllib2.urlopen(url)
status_code = proxied_request.code
mimetype = proxied_request.headers.typeheader or mimetypes.guess_type(url)
content = proxied_request.read()
except urllib2.HTTPError as e:
return HttpResponse(e.msg, status=e.code, mimetype='text/plain')
else:
return HttpResponse(content, status=status_code, mimetype=mimetype)
This proxies requests from PROXY_PATH+path to TARGET_URL+path.
The proxy is enabled and configured by adding a URL pattern like this to urls.py:
url(r'^PROXY_PATH/(?P<path>.*)$', proxy_to, {'target_url': 'TARGET_URL'}),
For example:
url(r'^images/(?P<path>.*)$', proxy_to, {'target_url': 'http://imageserver.com/'}),
will make a request to http://localhost:8000/images/logo.png fetch and return the file at http://imageserver.com/logo.png.
Query strings are forwarded, while HTTP headers such as cookies and POST data are not (it's quite easy to add that if you need it).
Note: This is mainly intended for development use. The proper way to handle proxying in production is with the HTTP server (e.g. Apache or Nginx).
I ran across this question while trying to answer it myself, and found this Django app:
http://httpproxy.yvandermeer.net/
...which is a little heavyweight for what I needed (recording and playback, requires a syncdb to add in model stuff). But you can see the code it uses in its generic proxying view, which is based on httplib2:
http://bitbucket.org/yvandermeer/django-http-proxy/src/1776d5732113/httpproxy/views.py
Am I right that you are asking about how to write view in Django that could accept incoming AJAX request, issue request to the remote server and then return received response to browser?
If so, then it's not really Django-specific question - remote calls could be done with Python's urllib2 or httplib, and then you just have to put:
return HttpResponse(received_response)
-- in your Django proxy-view. I assume no reponse processing here, because if it's just a proxy for AJAX call then JavaScript expects unprocessed data.

Resources