2

I'm looking for something that acts like a terminal but lets me have a "dialogue" with a server over http. Something like this :

$ connect http://myserver.com

Welcome to myserver.com  
Options
A - Fribble the obsticator
B - List Frogits
C - Show the log
Q - Quit

$ A
Obsticator fribbled
blah blah 
blah
$ C
Log file 
...

$ Q
Bye 

I'm not looking for anything clever that tunnels an actual unix command-line over http. Nor a text-mode browser. This will talk to a simple custom server that knows its being accessed this way and that will return plain-text, not html.

But it must be over http, not a different protocol. And I don't want to be doing curl-like commands like

$ curl http://myserver.com?opt=A

It should be able to capture the URL once. And turning the command into a CGI argument should be transparent to the user.

Update: Also, I'm not bothered about keeping this dialogue open within a single connection, each command sent and received can be a separate http request. (In fact, that's better as it allows the server to be simpler)

Update 2 : The reason I want this is that I want to build a simple, small web-service API using Python Hug ( http://www.hug.rest/ ) but it would be convenient to have access to a couple of its actions directly from the command-line rather than the browser.

Rather than adding the extra complexity, of talking a different protocol and managing a separate interaction listener, on the server, it would be good to have a simple command-line client to talk to the API with standard http requests.

So, is there anything like this? (Before I sit down and write one.)

  • 4
    Short answer is NO, http is not design for this kind of interaction. – Archemar Sep 16 '16 at 15:12
  • http was designed for sharing physics research papers .. it seems to have suffered considerable mission-creep since then :-) Is there any reason to think it would be a bad protocol for this? – interstar Sep 16 '16 at 15:15
  • The protocol just isn't really built that way. The closest thing I can think of is using ncat to connect to the port but, even then, you'd need to type in full HTTP requests and, in most cases, the connection will be closed before you even get one request off. – I_GNU_it_all_along Sep 16 '16 at 15:18
  • If you are willing to type GET /?opt=A HTTP/1.0 and server doesn't close connection , go for it. – Archemar Sep 16 '16 at 15:19
  • 1
    Is this question asking to do this with the Hypertext Transfer Protocol? Or is the requirement that it do its work with the specific well-known port number? – JdeBP Sep 16 '16 at 15:27
3

You can use telnet to connect to the server, knowing that ( I am assuming here that you want to use a webserver to communicate with) you will need to operate within the contraints of the HTTP spec.
For example the specification https://www.w3.org/Protocols/rfc2616/rfc2616.txt
states:

Origin servers MUST include a Date header field in all responses, except in these cases: ...

here is the terminal output of a "conversation" I had with a webserver over telnet.
Bearing in mind that the webservers configuration will determine how long the TCP connection is kept alive for - i.e. the time you have to type a properly formed HTTP request before the server will sever the TCP connection due to "inactivity". but this is configurable.
If you enter each request before timeout, you will essentially be sending many HTTP requests and responses over a single continuous TCP connection.

% telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1           <---- this in where you type characters "interactively"            
Host: localhost          <---- this in where you type characters "interactively"
                         <-- per the HTTP specification this has to be an emtpy line
                             to tell the server you are done with your "message"



HTTP/1.1 200 OK
Server: nginx/1.10.0 (Ubuntu)
Date: Sat, 17 Sep 2016 07:38:08 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive

45d
<html>
[truncated ... ]
</html>


0                      

GET / HTTP/1.1         <-- now you are back at prompt
Host: localhost            Note: you need to enter the `Host` header if you are talking 
                           to a webserver
HTTP/1.1 200 OK
Server: nginx/1.10.0 (Ubuntu)
Date: Sat, 17 Sep 2016 07:41:07 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive

45d
<html>
[truncated]

Obviously to get a cleaner "dialogue" you would need to clean up the output from the webserver or your application that would be handling the requests.

The nginx ttp_core_module is responsible for managing the default type using
http://nginx.org/en/docs/http/ngx_http_core_module.html#default_type

To add headers you can use the http_headers_module http://nginx.org/en/docs/http/ngx_http_headers_module.html

2

As long as you don't mind using curl as your backend, and you just don't want to have to type in the whole URL each time, you could run curl in a loop, something like this:

read -p "Server name: " s && curl -fs "$s" && while true; do read -p "$ " x && curl -fs "$s?opt=${x^^}" || break; done

which would also fit nicely into an alias if you didn't want to type or paste the whole thing in each time.

There's not a lot of error checking there, which is probably fine if you just want an easy way to talk to your own trusted server and aren't trying to hack your own script. A more advanced script could validate the server name or try to parse the returned web pages before displaying them, and of course both sides should defend against untrusted input.

I added two options to curl:

  • -f will exit with an error code 21 if the web page returns error 400 or above (useful for the quit command)
  • -s silent mode won't show connection data for each command.

Other than that, you'll see exactly what your server outputs for each query.

  • One issue with this is that it doesn't URL encode what's sent to the server ... so if you try to send a line with spaces it blows up. Any idea how to do that in shell-script? – interstar Sep 17 '16 at 22:41
  • upvote for explanation of the -f and -s options – the_velour_fog Sep 18 '16 at 0:09
1

OK.

Inspired by @drewbenn's answer, I wrote it myself in Python, using the Requests (http://requests.readthedocs.io/en/master/) library :

import requests
import sys

url = sys.argv[1]
print "Connecting ", url

r = requests.get(url)
print r.text
flag = True
while flag :
    s = raw_input()
    data = {"opt": s}
    r = requests.get(url, params=data)
    print r.text
1

If it's a RESTful HTTP API, particularly of the HATEOAS variety, then you could use Spring's rest-shell

https://github.com/spring-projects/rest-shell

Example usage:

http://localhost:8080:> discover
rel                href
========================================================
address            http://localhost:8080/address
family             http://localhost:8080/family
people             http://localhost:8080/person
profile            http://localhost:8080/profile

http://localhost:8080:> follow people
http://localhost:8080/person:> list
rel             href
===================================================
people.Person    http://localhost:8080/person/1
people.Person    http://localhost:8080/person/2
people.search    http://localhost:8080/person/search

http://localhost:8080/person:> get 1
...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.