32

I'm attempting to make use of cgminer's API using Python. I'm particularly interested in utilizing the requests library.

I understand how to do basic things in requests, but cgminer wants to be a little more specific. I'd like to shrink

import socket
import json

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 4028))

sock.send(json.dumps({'command': 'summary'}))

using requests instead.

How does one specify the port using that library, and how does one send such a json request and await a response to be stored in a variable?

2mac
  • 1,609
  • 5
  • 20
  • 35
  • 1
    I'm not sure to understand. That's why I post as a comment: [Request](http://docs.python-requests.org/en/latest/) is an HTTP library. You can specify the port in the URL `http://example.com:4028/...`. From what I can read in a hurry [here](https://github.com/ckolivas/cgminer/blob/master/API-README) `cgminer` provides a RPC API. But does it provide an HTTP interface? – Sylvain Leroux Aug 30 '14 at 13:40
  • I've re-posted as an answer as you seems to confirm what I've supposed. – Sylvain Leroux Aug 30 '14 at 13:59

3 Answers3

27

Request is an HTTP library.

You can specify the port in the URL http://example.com:4028/....

But, from what I can read in a hurry here cgminer provides a RPC API (or JSON RPC?) not an HTTP interface.

Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
27

As someone who has learned some of the common pitfalls of python networking the hard way, I'm adding this answer to emphasize an important-but-easy-to-mess-up point about the 1st arg of requests.get():

localhost is an alias which your computer resolves to 127.0.0.1, the IP address of its own loopback adapter. foo.com is also an alias, just one that gets resolved further away from the host.

requests.get('foo.com:4028')                #<--fails
requests.get('http://foo.com:4028')         #<--works usually  

& for loopbacks:

requests.get('http://127.0.0.1:4028')       #<--works
requests.get('http://localhost:4028')       #<--works

this one requires import socket & gives you the local ip of your host (aka, your address within your own LAN); it goes a little farther out from the host than just calling localhost, but not all the way out to the open-internet:

requests.get('http://{}:4028'.format(socket.gethostbyname(socket.gethostname())))  #<--works
Rob Truxal
  • 5,856
  • 4
  • 22
  • 39
  • 1
    `172.0.0.1` is incorrect for `localhost`. It's `127.0.0.1`. Typo, or is that why it's failing? – 2mac Apr 09 '17 at 00:22
  • 1
    That was indeed why it was failing. – Rob Truxal May 07 '18 at 00:20
  • 1
    what is the triple slash all about? where is the in the docs? `///` i tried googling but no find anything – red888 Nov 19 '18 at 06:37
  • Oh whoah interesting. That is a typo & this fails (at least as of 3.6) in python, but some browsers (tested on Firefox) appear to correct this. Technically `http:///` [wouldn't be a valid URI,](https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.2.2) so theoretically whatever URI parsing...thing/system you hit first should get mad at you or attempt to correct the malformed request. Anyhow: `nslookup` returns "` cannot find https:///google.com`", python throws an error, and Firefox corrects the URL for you. – Rob Truxal Nov 20 '18 at 01:09
3

You can specify the port for the request with a colon just as you would in a browser, such as r = requests.get('http://localhost:4028'). This will block until a response is received, or until the request times out, so you don't need to worry about awaiting a response.

You can send JSON data as a POST request using the requests.post method with the data parameter, such as

import json, requests
payload = {'command': 'summary'}
r = requests.post('http://localhost:4028', data=json.dumps(payload))

Accessing the response is then possible with r.text or r.json().

Note that requests is an HTTP library - if it's not HTTP that you want then I don't believe it's possible to use requests.

Kkelk
  • 136
  • 6