Find the port bound by snap-server - haskell

Using snap-server's httpServe method, I can setPort 0 to instruct the server to connect on the next free port. Unfortunately, once I have started the http server, I can't find any way to determine which port it actually started on. As an example, my first try started on port 2679 - is there any way to determine that number?

I wrote this patch, included with snap-server 0.9 and above, using which you can write:
let hook dat = print $ socketPort $ head $ getStartupSockets dat
let config = setStartupHook hook $ setPort 0 mempty
httpServer config ...
Now hook will be called after the server is ready, and will print the port it started on.

The Config structure has a bunch of getters, no?
getPort :: Config m a -> Maybe Int
Returns the port to listen on (for http)

Related

How to run web server (Warp) in async/concurrent mode?

I'm using https://hackage.haskell.org/package/warp-3.3.24/docs/Network-Wai-Handler-Warp.html
I don't know much about haskell concurrency. Say I would like to run two servers on different ports:
So I do:
do
Warp.run 3000 waiApp
Warp.run 3002 waiApp
Then server is run on 3000 is working, but it never gets to the next line.
I tried:
do
forkIO $ Warp.run 3000 waiApp
forkIO $ Warp.run 3002 waiApp
But it doesn't seem to work, each of them just stop after forking.
How to make it work properly? Also I want to allow the code below to be executed aslo.
UPD:
So the current solution is just to add
forever (threadDelay 1000)
in the end of the main, I wonder if it is the correct way to do this.
So, we should not allow the main thread to terminate. Something like this should work:
do
a1 <- Async.async $ Warp.run 3000 waiApp
a2 - Async.async $ Warp.run 3002 waiApp
...
Async.waitAny [a1, a2]

Use ReactPHP Socket to open a ws:// socket

I've been trying to get ReactPHP socket up and running for a bit now, once up, I can telnet to it on the specified port but I cannot use websocat or any js lib to connect via ws:// protocol. Any help would be appreciated.
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server('127.0.0.1:8000', $loop);
$socket->on('connection', function(ConnectionInterface $connection) use ($colors) {
$connection->write("Hello " . $connection->getRemoteAddress() . "!\n");
$connection->on('data', function($data) use ($connection){
$connection->write('received: ' . strtoupper($data));
});
});
echo "Listening on {$socket->getAddress()}\n";
$loop->run();
Server:
Listening on tcp://127.0.0.1:8000
Client:
websocat ws://localhost:8000
websocat: WebSocketError: HTTP failure
websocat: error running
For anyone struggle with this. React opens a low-level tcp socket which cannot be used with socket.io type ws:// connections. You will need to use a wrapper like Ratchet php.

How to remotely inspect data with Heroku / RedisCloud / Node.js

I have RedisCloud running with Node.js on Heroku and would like to inspect data remotely, ideally using the command line in OS X. I've seen this:
How can I remotely inspect the data in my RedisCloud DBs?
but it is for Ruby and doesn't work for me. (I get redis-cli: command not found.)
I'm using the node_redis client:
https://github.com/mranney/node_redis
The requires in my server app look like this:
var express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server),
redis = require('redis'),
ioredis = require('socket.io-redis'),
url = require('url'),
redisURL = url.parse(process.env.REDISCLOUD_URL),
redis-cli isn't a Ruby tool, it is a standard part of the Redis package. The easiest way of getting on your Mac is to download and build Redis from https://github.com/antirez/redis. Once you've done that, your laptop will be able to use the compiled binary.
Note that when in a bind and in need of connecting to Redis, you can also use plain telnet.

basic node website returns "Cannot GET /" when hosted with forever.js

I'm trying to get my first production node website up (just a basic hello world on my production web server).
The below is what I'm using (basic http proxy to pass off apache websites to port :9000 and node websites to port :8000). I know this part works because apache vhosts are forwarded as I expect. What does not work however is the node part -instead I get the error below
"Cannot GET /"
This is running node 0.8.1 on Ubuntu 12.04
I'm hosting this with forever.js (forever start foo.js). when I echo the NODE_ENV -it shows "production"
It might also be noted that I don't have node_modules on the path (as you will see in my require statements) **not sure if this has anything to do with my issue
var httpProxy = require('/usr/local/lib/node_modules/http-proxy/lib/node-http-proxy');
var express = require('/usr/local/lib/node_modules/express/lib/express');
httpProxy.createServer(function (req, res, proxy) {
var nodeVhosts = ['www.mysite.com'];
var host = req.headers['host'];
var port = nodeVhosts.indexOf(host) > -1
? 8000
: 9000;
proxy.proxyRequest(req, res, {host: 'localhost', port: port});
}).listen(80);
var one = express.createServer();
one.get('/', function(req, res){
res.send('Hello from app one!')
});
var app = express.createServer();
app.use(express.vhost('localhost', one));
app.listen(8000);
Since you are running Ubuntu, you might take a look at upstart. In case you don't know, upstart replaces the old-school-unix init-scripts approach to starting and stopping services. (Those were dark, scary days!) If you want your app to start automatically when your box boots/reboots and restart automatically after it (your app) crashes, then you want upstart. Learning the basics of upstart is easy, and then you have a tool that you can use over and over again, whether it's node, apache, nginx, postfix, mongodb, mysql, whatever!
I mean no disrespect to the good folks who work on the forever module. Arguably, it does have a solid use case, but too often it is used to imperfectly duplicate the bedrock which is already on your system -- upstart. Also, you might Google for some of the comments made by experienced users and some node.js committers about the forkability of node.js and the pitfalls, which are very relevant to forever.
I'd like to post links, but I don't have enough rep yet. Hopefully what I wrote is enough to google on.
Good luck!
http-proxy module doesn't change the host header of the request, and that's what connect/express vhost uses to distinguish virtualhosts.
In this line:
proxy.proxyRequest(req, res, {host: 'localhost', port: port});
you tell the proxy server to proxy the unchanged request to localhost:port.
So what you need to do is to change:
var app = express.createServer();
app.use(express.vhost('localhost', one));
app.listen(8000);
to:
var app = express.createServer();
app.use(express.vhost('www.mysite.com', one));
app.listen(8000);
and it should work.
Alternatively you can simply set the req.headers.host to localhost before proxying.

Command line for running server

I have a Node server which I would like to debug. Once I've started the server
node server.js
I want to execute functions defined in server.js from a command line. The usual Node REPL "blocks" after the server has started.
For example, if server.js defines the function addBlogPost I want to locally call addBlogPost() and observe changes in the database without passing through a GUI.
Is there an easy way to do this?
You can use the repl module to create a new REPL instance:
repl = require("repl")
r = repl.start("node> ")
r.context.pause = pauseHTTP;
r.context.resume = resumeHTTP;
Now inside the REPL you can use pause() to call pauseHTTP() and resume() to call resumeHTTP().

Resources