Skip to content

Commit

Permalink
Add xquery plugin (#15)
Browse files Browse the repository at this point in the history
* Add xquery plugin

* strip id

* proxy request

* convert data to json

* logging e

* misc

* print logs

* proxy to xq-ng-rp

* graphql proxy request

* xquery auth middleware

* common middleware

* ignore api-key for /help endpoints

Co-authored-by: leonVrashitov <[email protected]>
  • Loading branch information
pom11 and leonVrashitov authored Dec 20, 2021
1 parent 1453892 commit 11d6c92
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 4 deletions.
13 changes: 9 additions & 4 deletions plugins/ethpassthrough/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,21 @@ def authenticate(f):
@wraps(f)
def wrapper(*args, **kwargs):
logging.debug('%s %s', request.headers.get('Api-Key'), request.view_args['project_id'])
if 'Api-Key' not in request.headers:
return api_error_msg('Missing Api-Key header', ApiError.MISSING_API_KEY)
if 'help' not in request.base_url:
if 'Api-Key' not in request.headers:
return api_error_msg('Missing Api-Key header', ApiError.MISSING_API_KEY)
if 'project_id' not in request.view_args:
return api_error_msg('Missing project-id in url', ApiError.MISSING_PROJECT_ID)

project_id = request.view_args['project_id']
api_key = request.headers.get('Api-Key')
if 'help' not in request.base_url:
api_key = request.headers.get('Api-Key')

with db_session:
project = Project.get(name=project_id, api_key=api_key)
if 'help' in request.base_url:
project = Project.get(name=project_id)
else:
project = Project.get(name=project_id, api_key=api_key)

if project is None:
return project_not_exists()
Expand Down
104 changes: 104 additions & 0 deletions plugins/xquery/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Copyright (c) 2020 The Blocknet developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.

import json
import logging
import os
import threading

import requests
from flask import Blueprint, Response, g, jsonify, request
from plugins.ethpassthrough.middleware import authenticate
from plugins.ethpassthrough.util.request_handler import RequestHandler

app = Blueprint('xquery', __name__)
req_handler = RequestHandler()

@app.errorhandler(400)
def bad_request_error(error):
response = jsonify({
'error': 'Bad Request ' + error
})
return response


@app.errorhandler(500)
def internal_server_error(error):
response = jsonify({
'error': 'Internal Server Error'
})
return response


@app.errorhandler(401)
def unauthorized_error(error):
response = jsonify({
'error': 'Unauthorized User Access'
})
return response


@app.route('/xrs/xquery/<project_id>/', methods=['POST'], strict_slashes=False)
@app.route('/xrs/xquery/<project_id>/<path:path>', methods=['POST'], strict_slashes=False)
@authenticate
def handle_request(project_id, path=None):
try:
host = os.environ.get('XQUERY_HOST', 'http://localhost:81')
port = host.split(":")[-1]
headers = {'content-type': 'application/json'}
if path in ['help','help/'] or path==None:
url = host+'/help'
response = requests.get(url, timeout=15)
text = response.text
text = text.replace(f"localhost:{port}",f"127.0.0.1/xrs/xquery/{project_id}")
return Response(headers=response.headers.items(), response=text)
elif 'help' not in path:
url = host + '/' + path
response = requests.post(url, headers=headers, json=request.get_json(), timeout=15)
resp = json.dumps(response.json())
header = response.headers
header['Content-Type']='application/json'
header['Content-Length']=len(resp)
header['Keep-Alive']='timeout=15, max=100'
header['Content-Encoding']='UTF-8'
update_in_background_api_count(project_id)
return Response(headers=header.items(), response=resp)
else:
url = host + '/' + path
response = requests.get(url, timeout=15)
if 'help/graph' in path:
resp = json.dumps(response.json())
header = response.headers
header['Content-Type']='application/json'
header['Content-Length']=len(resp)
header['Keep-Alive']='timeout=15, max=100'
return Response(headers=header.items(), response=resp)
else:
resp = response.text
return Response(headers=headers.items(), response=resp)
except Exception as e:
logging.debug(e)
response = {
'exception': f'{e}',
'message': "An error has occurred!",
'error': 1000
}
return Response(headers=headers, response=json.dumps(response), status=400)


@app.route('/xrs/xquery', methods=['HEAD', 'GET'])
def xquery_root():
return '''
<h1>xquery is supported on this host</h1>
'''


def update_in_background_api_count(project_id):
update_api_thread = threading.Thread(target=update_api_count, name="update_api_count", args=[project_id])
update_api_thread.start()

def update_api_count(project_id):
res = req_handler.post_update_api_count(project_id)
logging.debug('update_api_count {} {}'.format(project_id, res))

7 changes: 7 additions & 0 deletions wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ def load_plugins():
except Exception as e:
logging.error('Failed to load eth_passthrough plugin: %s', getattr(e, 'message', repr(e)))

if 'xquery' in plugins:
try:
from plugins.xquery import routes
app.register_blueprint(routes.app)
except Exception as e:
logging.error('Failed to load xquery plugin: %s', getattr(e, 'message', repr(e)))


# Set the bitcoin library parameters including chain and service node signing key.
if __name__ == 'wsgi':
Expand Down

0 comments on commit 11d6c92

Please sign in to comment.