How does an Elixir/Phoenix app know its own websocket uri? - websocket

I'm beginning to use web sockets with an Elm frontend and a Elixir/Phoenix backend. The Phoenix server needs to tell the Elm app what uri to connect to. (E.g., ws://localhost:4000/socket/websocket in the development environment, but something else in the production environment.)
I was hoping there was something the equivalent of static_url, but I can't find it. Is there?
(I know I could hardcode the possibilities, but it seems like Phoenix must already know them.)

One way, via Chris McCord, is to change this line in YourApp.Endpoint:
socket "/socket", Eecrit.UserSocket
... with this:
#socket_mount "/socket"
def socket_uri() do
ws_url = String.replace_leading(url(), "http:", "ws:")
ws_url <> #socket_mount
end
socket #socket_mount, Eecrit.UserSocket
Note that this requires the client to add the transport /websocket to the end of the URI.

I really figured there'd be a helper function in Phoenix.Endpoint for this, but I didn't find anything.
There's likely a better solution, but my quick-and-dirty response would be to examine the conn argument that is passed into any Phoenix controller. It has a bunch of useful fields, like host and port, and a list of request headers (like host, from which you could build the websocket URL.

Related

VueJS SPA dynamic baseURL for axios

I've searched and searched and can't seem to find a pattern for this. I'd consider myself an intermediate Vue dev, however, the backend is my strong suit. I'm working on an app that will be white-labeled by resellers. While it's possible to have multiple builds, avoiding that would be ideal. The setup is a stand-alone vue-cli SPA connecting to a Laravel api backend and using the Sanctum auth package. So I need calls to the same domain. The issue: resellers will be on their own domain. The ask: Is there a pattern/solution for dynamically loading configs (mainly baseURL) for different domains (other items would by theme/stylesheet). Currently I have a few typical entries:
i.e. axios.defaults.baseURL = process.env.VUE_APP_API_BASE_URL
Basically, based on the domain the site is being served on, I'd like a dynamic/runtime config. I feel like this has been solved, but I can't seem to use the right search terms for some direction, so anything is helpful. I've tried a few things:
1) Parsing in js, but can't seem to get it to run early enough in the process to take effect? It seems to work, but I can't get it to "click"
2) Hit a public API endpoint with the current domain and get the config. Again, can implement, but can't seem to get it to inject into the Vue side correctly?
Any resources, pattern references or general guidance would be much appreciative to avoid maintaining multiple builds merely for a few variables. That said, I don't think there's much overhead in any of this, but also open to telling my I'm wrong and need multiple builds.
End Result
url visited is https://mydomaincom
then baseURL = https://api.mydomiancom
url visited https://resellerdomaincom
then baseURL=https://api.resellerdomaincom
I don't think there is a common pattern to solve your problem - I haven't found anything on the net.
The best software design solution could be the following:
have a single back-end
distribute only the client to your customers/resellers
Obviously the back end could see the domain of the application from which the request comes and manage the logic accordingly.
Good luck with your project.
Honestly how the question is put it's not really clear to me. Although my usual pattern is to:
Create an axios instance like so:
export const axiosInstance = axios.create({
// ...configs
baseURL: process.env.VUE_APP_URL_YOU_WOULD_LIKE_TO_HIT
})
and then whenever I make a request to some api, I would use this instance.
EDIT: According to your edit, you can either release the client to each customer, and have a .env file for each and every of them, or you can have a gateway system, where the client axios end point is always the same, hitting always the same server, and then from there the server decides what to ping, based on your own logic

Ruby - Handle incoming HTTP POST?

I seem to be missing something basic, as I don't know how to capture and then handle an incoming HTTP Post. I'm a C/C++ developer learning Ruby for the first time, and I've never dealt with web-stuff in my life.
I'm writing my first Slack Webhook, and slack will send data similar to this to my webserver:
token=ZLAmT1sKurm2KwvmYDR9hbiV
team_id=T0001
team_domain=example
channel_id=C2147483705
channel_name=test
user_id=U2147483697
user_name=Steve
command=/weather
text=94070
response_url=https://hooks.slack.com/commands/1234/5678
I have no idea how to accept this POST request, and send it to my application for processing.
I assume it's similar to handling argv and argc for a terminal application, but I'm stuck writing the first few lines.
I've searched for a solution, but it seems like I'm asking the wrong questions.
I currently have a Puma/Sinatra webserver running on heroku, with the Procfile containing:
web: bundle exec puma -p $PORT (I also have no idea what port is assigned to it.)
Similar to this answer, Sinatra provides a DSL to accept POST requests. Within the block, the data will be accessible in the params hash. Something like
post '/my_endpoint' do
content_type :json
#team_id = params[:team_id]
res = do_stuff_with_channel_id params[:channel_id] # passing the value to a custom method example
{my_response: res}.to_json #simple example of returning JSON in response
end
Sinatra Docs on routing
HTH

Url Rewrite in Self-Hosted environment

I have a SignalR-service in two api-versions running in self-hosted Owin processes. I want to route traffic for api.service.com to either api1.service.com or api2.service.com depending on a http-header (api-ver) in a request. Is this possible to do with Owin middleware or in some other way without having to host this in IIS or using a 3rd party reverse proxy or similar? I was hoping it could be done with "Url Rewriting" but I don't know if this is possible in self-hosting?
Have you considered this, I am in the same boat and thinking it will resolve my problem. But to answer your question it does seem possible in self-hosted environments.
Owin.UrlRewrite
EDIT - This library doesn't work (at least I sure can't get it to work). I did experiment with an OWIN middleware of my own and it can be done with redirects but there is a flicker in the URL to essentially the hashtag url (before the client router kicks in (Aurelia in my case) and makes it the non-hash url). Best I can say is this is a limited use case (Self-hosting with need for URL Rewriting) as I cannot find a pre-made solution to do this.

mod_rewrite and server environment variables

The setup I have is as follows:
I have one Apache server acting as a URL rewriting engine (SERVER1).
I have a second server (Apache too) which runs a web application (SERVER2). First tries to authenticate users. Part of the authentication protocol involves a lot of redirection between that application server and the authentication server.
My problem is that once the authencation is successfull, the authentication server needs to redirect the user back to the application server, which is only visible from SERVER1. Effectively, SERVER2 needs to be able to reconstruct a URL based on SERVER1's parameters.
Most of the environement variable are helpful i.e. I know the host name, script name, page called etcc but I can 't figure out wether the call was made through HTTP or HTTPS: that information is wiped in the rewrite process by SERVER1...
Anybody knows if/how I can get that information through environement variables? I am limited in that I can't use query string parameters...
Thanks all !
This may sound strange, but I have found part of the answer to my question.
The rewrite engine (at least in Apache 2, I haven't looked anywhere else) allows for writting extra request header.
The rule should look something like that.
RewriteRule .* -
[E=INFO_PATH_INFO:%{PATH_INFO},NE]
Put simple, it creates a new header called INFO_PATH_INFO and sets the value to PATH_INFO.
( For more info check out http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html )
Then it can be retrieved in any languages.
For info I am using Oracle's OWA which adds an extra layer of complication due to the fact that the default environment variables are limited to a few and additional variables need to be specified in thr dads.conf
Hope this will help anyone !

Ruby: Get currently logged in user on windows

In C# I can get the current user of a web app using the HttpContext, however, I can't figure out how to do this in Ruby. Is there any way of doing this?
FOR THOSE OF YOU SAYING IT IS IMPOSSIBLE, HERES PROOF:
http://www.codeproject.com/KB/aspnet/How_to_NT_User_Name.aspx
Well, to get the current username, there's this:
puts ENV['USERNAME']
Or go to the Win32API.
require 'dl/win32'
def get_user_name
api = Win32API.new(
'advapi32.dll',
'GetUserName',
'PP',
'i'
)
buf = "\0" * 512
len = [512].pack('L')
api.call(buf,len)
buf[0..(len.unpack('L')[0])]
end
puts get_user_name
Edit: And I'm an idiot. This isn't what you asked for at all. Oh well, it took me time to dig this out of my code, so it might as well stay here for anyone else wondering :P
Edit again: OK, it turns out I'm not an idiot after all. This is what you want. When I went back and re-read your question, the HttpContext threw me off, and I thought it was the current username from HTTP auth or something.
To get the username of the current user on client machine you can use this
ENV['USERNAME']
If you're using Rails try: request.env['HTTP_REMOTE_USER']
I think what you mean is how you can retrieve the username that the user used to login to the web application. That will differ depending on what authentication mechanism you're using. Some Apache authentication modules, for example, will pass REMOTE_USER (e.g. the Kerberos module), the CAS Single-Sign-On module passes CAS-USER, etc. Standard digest authentication and such uses the Authentication header. You should be able to access these using request.env[HEADER] as someone else pointed out above. Check out the documentation on how your authentication layer is passing on the user in the HTTP request.
Is your c# code running as a .NET plugin/client-side code or is it ENTIRELY server side? Your ruby code would be entirely server side. According to the MS docs, only stuff running in the CLR sandbox can really get to that information:
http://msdn.microsoft.com/en-us/magazine/cc163700.aspx (under Defining the sandbox).
One thing interesting to note is that sites registered under LocalIntranet have access to that information. I'm not sure off hand how this maps to security zones in IE though.
The thing to understand is that LOGON_USER is NOT visible to the browser sandbox anymore than the browser can see the contents of a filesystem path on your system. The fact that your c# code sees it almost certainly indicitive of some clientside component passing it upstream.
You have the option of implementing mod_ntlm under apache and pushing the headers downstream. I don't have the points to post a second link but google 'rails ntlm sso' and see the rayapps.com link.
but if your app isn't Rails based, you'll have to port that to your server code. You can also checkout rack-ntlm if your app is rack compliant.
[RUBY ON RAILS ONLY]
This is what worked for me but there are some limitations:
won't work in Chrome: undefined method 'encode' for nil:NilClass
won't validate user credentials
If you don't care about these issues, go ahead:
In your rails application, add Rekado's gem to your Gemfile: gem 'ntlm-sso', '=0.0.1'
Create an initialiser config/initializers/ntlm-sso.rb with:
require 'rack'
require 'rack/auth/ntlm-sso'
class NTLMAuthentication
def initialize(app)
#app = app
end
def call(env)
auth = Rack::Auth::NTLMSSO.new(#app)
return auth.call(env)
end
end
On your application.rb file, add the line: config.middleware.use "NTLMAuthentication"
Call request.env["REMOTE_USER"] on your view or controller to get current username.
PS: Let me know if you find anyway to make it work on Chrome or to validate user credentials.

Resources