ReductionServer: main
#!/usr/bin/python
import bottle
from bottle import route
from bottle import response
import sys
import logging
import time
import signal
import config.config
import data.messages
from content.validator.filename import FileValidator
from query.handler import QueryHandler
from result.handler import ResultHandler
from status.handler import StatusHandler
from methods.handler import MethodsHandler
'''
Bottle reduction server
To old_test use curl:
-X GET | HEAD | POST | PUT | DELETE
Use curl -v for verbose
It assumes:
- One server will run for a single instrument
- Just a single file is handled by the server at the same time.
- The submission of new file will invalidates the stored data of the previous one
'''
logger
= logging.getLogger("server")
# Handle signals
def signal_handler(signal_, frame):
logger.info("Server
caught a signal! Server is shutting down...")
logger.info("Killing
running processes...")
# TODO
# Any cleanups needed
time.sleep(0.1)
logger.info("Server
shut down!")
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
@route('/',
method=['GET','POST'])
def homepage_get():
'''
Home page:
Open with a browser or:
curl http://localhost:8080/
'''
logger.debug('Home
page was requested.')
return
data.messages.Messages.success("Server
is up and running.")
@route('/file/<numor:re:[0-9]+>',
method='POST')
def fileHandler(numor):
'''
User can send a binary / ascii file or an url for a file location.
To test:
curl -v --noproxy '*' -X POST --data-binary @094460.nxs http://localhost:8080/file/094460
curl -v --noproxy '*' -X POST --data "`pwd`" http://localhost:8080/file/094460
'''
logger.debug("Receiving
file by HTTP POST with numor = %s" %
numor)
content = bottle.request.body.read()
v = FileValidator(content)
message = v.validateFile(numor)
logger.debug(message)
return message
#@route('/query/<numors:re:[0-9,]+>',
method='POST')
@route('/query',
method='POST')
def query():
'''
Get the query results. Sent json by the client should be of the form:
{
"method" : "theta_vs_counts", "params"
: { "numors":[94460]} }
'''
content = bottle.request.body.read()
logger.debug("RAW
Query received: " +
str(content))
qh = QueryHandler(content)
message = qh.process()
logger.debug(message)
return message
@route('/results/<queryId>',
method=['POST','GET'])
def results(queryId):
"""
Return the contents of localDataStorage has json
Test:
curl -X POST http://localhost:8080/results/<queryId>
"""
r = ResultHandler(queryId)
message = r.getQuery()
logger.debug(message)
return message
@route('/resultszipped/<queryId>',
method=['POST','GET'])
def resultszipped(queryId):
"""
Return the contents of localDataStorage has json
Test:
curl -X POST http://localhost:8080/resultszipped/<queryId>
"""
r = ResultHandler(queryId)
message = r.getQueryZipped()
logger.debug("Zipped
content! size = %d"%len(message))
bottle.response.set_header('Content-Encoding',
'gzip')
return message
@route('/status',
method=['POST','GET'])
def status():
"""
Returns data of queries
"""
r = StatusHandler()
message = r.getQueries()
logger.debug(message)
# Because the response is [...] it's not considered json
response.content_type = 'application/json'
return message
@route('/methods',
method=['POST','GET'])
def methods():
h = MethodsHandler()
message = h.getAllMethods()
logger.debug(message)
return message
@route('/methodsavailable',
method=['POST','GET'])
def methodsAvailable():
h = MethodsHandler()
message = h.getMethodsForThisInstrument()
logger.debug(message)
return message
def main(argv):
# command line options
from config.config import options
# Launch http server
bottle.debug(True)
try :
bottle.run(host=options.server, port=options.port)
except Exception as e:
#logger.exception("Web
server cannot run: " + str(e))
logger.error("Web
server cannot run: " +
str(e))
logger.info("Server
shutdown...")
if __name__ == '__main__':
main(sys.argv)
#!/usr/bin/python
import bottle
from bottle import route
from bottle import response
import sys
import logging
import time
import signal
import config.config
import data.messages
from content.validator.filename import FileValidator
from query.handler import QueryHandler
from result.handler import ResultHandler
from status.handler import StatusHandler
from methods.handler import MethodsHandler
'''
Bottle reduction server
To old_test use curl:
-X GET | HEAD | POST | PUT | DELETE
Use curl -v for verbose
It assumes:
- One server will run for a single instrument
- Just a single file is handled by the server at the same time.
- The submission of new file will invalidates the stored data of the previous one
'''
logger
= logging.getLogger("server")
# Handle signals
def signal_handler(signal_, frame):
logger.info("Server
caught a signal! Server is shutting down...")
logger.info("Killing
running processes...")
# TODO
# Any cleanups needed
time.sleep(0.1)
logger.info("Server
shut down!")
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
@route('/',
method=['GET','POST'])
def homepage_get():
'''
Home page:
Open with a browser or:
curl http://localhost:8080/
'''
logger.debug('Home
page was requested.')
return
data.messages.Messages.success("Server
is up and running.")
@route('/file/<numor:re:[0-9]+>',
method='POST')
def fileHandler(numor):
'''
User can send a binary / ascii file or an url for a file location.
To test:
curl -v --noproxy '*' -X POST --data-binary @094460.nxs http://localhost:8080/file/094460
curl -v --noproxy '*' -X POST --data "`pwd`" http://localhost:8080/file/094460
'''
logger.debug("Receiving
file by HTTP POST with numor = %s" %
numor)
content = bottle.request.body.read()
v = FileValidator(content)
message = v.validateFile(numor)
logger.debug(message)
return message
#@route('/query/<numors:re:[0-9,]+>',
method='POST')
@route('/query',
method='POST')
def query():
'''
Get the query results. Sent json by the client should be of the form:
{
"method" : "theta_vs_counts", "params"
: { "numors":[94460]} }
'''
content = bottle.request.body.read()
logger.debug("RAW
Query received: " +
str(content))
qh = QueryHandler(content)
message = qh.process()
logger.debug(message)
return message
@route('/results/<queryId>',
method=['POST','GET'])
def results(queryId):
"""
Return the contents of localDataStorage has json
Test:
curl -X POST http://localhost:8080/results/<queryId>
"""
r = ResultHandler(queryId)
message = r.getQuery()
logger.debug(message)
return message
@route('/resultszipped/<queryId>',
method=['POST','GET'])
def resultszipped(queryId):
"""
Return the contents of localDataStorage has json
Test:
curl -X POST http://localhost:8080/resultszipped/<queryId>
"""
r = ResultHandler(queryId)
message = r.getQueryZipped()
logger.debug("Zipped
content! size = %d"%len(message))
bottle.response.set_header('Content-Encoding',
'gzip')
return message
@route('/status',
method=['POST','GET'])
def status():
"""
Returns data of queries
"""
r = StatusHandler()
message = r.getQueries()
logger.debug(message)
# Because the response is [...] it's not considered json
response.content_type = 'application/json'
return message
@route('/methods',
method=['POST','GET'])
def methods():
h = MethodsHandler()
message = h.getAllMethods()
logger.debug(message)
return message
@route('/methodsavailable',
method=['POST','GET'])
def methodsAvailable():
h = MethodsHandler()
message = h.getMethodsForThisInstrument()
logger.debug(message)
return message
def main(argv):
# command line options
from config.config import options
# Launch http server
bottle.debug(True)
try :
bottle.run(host=options.server, port=options.port)
except Exception as e:
#logger.exception("Web
server cannot run: " + str(e))
logger.error("Web
server cannot run: " +
str(e))
logger.info("Server
shutdown...")
if __name__ == '__main__':
main(sys.argv)