通过套接字连接到第二台服务器 API

Connect to second server API trough sockets

我正在 Python 中编写一个项目,它将有两个不同的(独立的)应用程序。

  1. 代理(普通Python代码,无框架)
  2. API到send/receiveJSON的数据库(用tornado 4.4框架写的)

我的项目将做这样的事情:

  1. 在数据库应用程序中,您可以添加过滤器:1 - 要过滤掉网页的锚标记,2 - URL 要赋予 403 状态的模式。
  2. 特定 URL (api/send-to-world/filter_type/) 上的数据库应用程序为 JSON 提供 filter_type = filter_type 的所有过滤器(来自以上)
  3. 在访问网页时,代理首先通过在上面的 URL 上捕获一个 JSON 来获取过滤器,然后进行过滤
  4. 为了统计,过滤后的内容被发送到数据库API接收到一个JSON(url:/api/receive-from-world/)并将内容保存到数据库.

为了测试项目,我将应用程序放在我的本地主机上:

  1. 端口 8000 上的代理服务器
  2. 900 端口上的数据库应用程序

由于 Tornado 框架编写了两个应用程序,该项目运行良好,但出于个人原因,我想让 PROXY 更底层 -> 使用套接字。

为此,我将 Proxy 应用程序重新编写为纯 Python 代码,但我遇到了一个小问题。问题是,当我创建一个套接字并且我想从数据库 API 接收一个 JSON 时,数据库应用程序给我一个 404 错误(而如果我在数据库上访问 URL它工作正常)。我不知道可能是什么问题。

我的代理 class 使用 send_json 和套接字创建方法:

class Proxy(object):
    u"""The PROXY class."""
    (...)

    def get_remote_response(self, host, port, data):
        u"""Method that creates a socket to the remote_address and gets the response.
        :param host: remote_host,
        :param port: remote_port,
        :param data: data to send.
        :return response: the response without the headers.
        """
        response_text = ''
        try:
            remote_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            print "Trying to connect to:%s : %s \n\n" % (host, port)
            remote_sock.connect((host, port))
            remote_sock.send(data)
            remote_sock.settimeout(0.5)
            while True:
                try:
                    response = remote_sock.recv(self.buffor_size)

                    if len(response) == 0:
                        break
                except socket.error:
                    break
                response_text += response
        except socket.error, msg:
            print str(msg)
        remote_sock.close()
        response = response_text[response_text.index('\r\n\r\n') + 1:]
        return response

    def get_filters(self, filter_id, **kwargs):
        u"""Method that gets a JSON with filters from the remote server
        :param filter_id: filter id.
        :return filters: list of filters from the remote server.
        """
        filters = list()
        remote_host = '127.0.0.1'
        remote_port = 9000
        request_url = 'http://%s:%s/api/send-to-world/%s/' % (remote_host, str(remote_port), filter_id)
        first_line_of_request = 'GET ' + request_url + ' HTTP/1.1\r\n'
        headers = {
            'Host': remote_host,
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }
        request = first_line_of_request
        for header in headers:
            request += '%s: %s\r\n' % (header, headers[header])
        request += '\r\n'

        print "request:\n", request
        response = self.get_remote_response(remote_host, remote_port, request)
        print "response:\n", response
        if response:
            data = None
            try:
                my_json = response
                data = json.loads(my_json.decode('utf-8'))
            except ValueError:
                message = 'Cannot parse JSON.'
                # self.send_error(400, message=message)
            filters = []
            for one_filter in data:
                filters.append((one_filter.get('filter_id'), one_filter.get('filter_name')))
        return filters

PROXY上的绑定、监听、接受已经完成,我想这里就不用上传了。如果是这样,就这么说:)

我留下了打印件,以便您可以查看数据库应用程序中的内容:

要求:

request: GET http://127.0.0.1:9000/api/send-to-world/2/ HTTP/1.1 Host: 127.0.0.1 Content-Type: application/json Accept: application/json

响应:

Trying to connect to:127.0.0.1 : 9000 response: Traceback (most recent call last): File "/home/dave/.virtualenvs/teleV1/local/lib/python2.7/site-packages/tornado/web.py", line 1446, in _execute result = self.prepare() File "/home/dave/.virtualenvs/teleV1/local/lib/python2.7/site-packages/tornado/web.py", line 2174, in prepare raise HTTPError(self._status_code) HTTPError: HTTP 404: Not Found

尝试获取过滤器时来自数据库应用程序的日志:

tornado working on port 9000 WARNING:tornado.access:404 GET http://127.0.0.1:9000/api/send-to-world/2/ (127.0.0.1) 2.75ms

当我通过网络浏览器访问它时,它给了我 JSON。

总结一下:如何使用套接字连接从我的数据库应用程序接收 JSON?我认为如果服务器在不同的端口上工作,那么问题不应该出在 host: 127.0.0.1 上。如果我错了,我不能在一台计算机上做这样的事情,那么请纠正我:)

我怀疑这是问题所在,但你说你的数据库应用程序在端口 900 上侦听,但你的代理正在连接到端口 9000...

不要在 HTTP 请求中包含协议、主机名和端口 headers,因此更改

request_url = 'http://%s:%s/api/send-to-world/%s/' % (remote_host, str(remote_port), filter_id)

request_url = '/api/send-to-world/%s/' %filter_id

例如,让您的代理从 whosebug.com 获取这篇文章:

remote_host = 'whosebug.com'
remote_port = 80
request_url = 'posts/43481916'
first_line_of_request = 'GET ' + request_url + ' HTTP/1.1\r\n'
headers = {
    'Host': remote_host,
    'Content-Type': 'text/html',
    'Accept': 'text/html'
}
request = first_line_of_request
for header in headers:
    request += '%s: %s\r\n' % (header, headers[header])
request += '\r\n'
response = self.get_remote_response(remote_host, remote_port, request)