2019-01-19 07:54:11 +01:00
import aiohttp
2019-01-19 07:58:37 +01:00
import validators
2019-01-19 07:38:13 +01:00
2019-01-19 07:25:23 +01:00
from sanic import Sanic
2019-01-19 07:54:11 +01:00
from sanic . log import logger
2019-01-19 07:38:13 +01:00
from sanic . response import html , json as json_response
from sanic . exceptions import InvalidUsage
2019-01-19 07:25:23 +01:00
app = Sanic ( )
2019-01-19 07:38:13 +01:00
@app.route ( " /check/ " , methods = [ " POST " ] )
async def check_http ( request ) :
ip = request . ip
try :
data = request . json
except InvalidUsage :
2019-01-19 07:54:11 +01:00
logger . info ( f " Unvalid json in request, body is : { request . body } " )
2019-01-19 07:38:13 +01:00
return json_response ( {
" status " : " error " ,
2019-01-19 08:08:36 +01:00
" code " : " error_bad_json " ,
" content " : " InvalidUsage, body isn ' t proper json " ,
2019-01-19 07:38:13 +01:00
} )
2019-01-19 07:54:11 +01:00
if not data or " domain " not in data :
logger . info ( f " Unvalid request didn ' t specified a domain (body is : { request . body } " )
2019-01-19 08:08:36 +01:00
return json_response ( {
" status " : " error " ,
" code " : " error_no_domain " ,
" content " : " request must specify a domain " ,
} )
2019-01-19 07:38:13 +01:00
domain = data [ " domain " ]
2019-01-19 07:58:37 +01:00
if not validators . domain ( domain ) :
logger . info ( f " Invalid request, is not in the right format (domain is : { domain } ) " )
2019-01-19 08:08:36 +01:00
return json_response ( {
" status " : " error " ,
" code " : " error_domain_bad_format " ,
" content " : " domain is not in the right format (do not include http:// or https://) " ,
} )
2019-01-19 07:58:37 +01:00
2019-01-19 07:38:13 +01:00
# TODO DNS check
2019-01-19 07:54:11 +01:00
async with aiohttp . ClientSession ( ) as session :
try :
async with session . get ( " http:// " + domain , timeout = aiohttp . ClientTimeout ( total = 30 ) ) as response :
# XXX in the futur try to do a double check with the server to
# see if the correct content is get
await response . text ( )
logger . info ( f " Success when checking http access for { domain } asked by { ip } " )
# TODO various kind of errors
except aiohttp . client_exceptions . ClientConnectorError :
2019-01-19 08:08:36 +01:00
return json_response ( {
" status " : " error " ,
" code " : " error_http_check_connection_error " ,
" content " : " connection error, could not connect to the requested domain, it ' s very likely unreachable " ,
} )
2019-01-19 07:54:11 +01:00
except Exception :
import traceback
traceback . print_exc ( )
2019-01-19 08:08:36 +01:00
return json_response ( {
" status " : " error " ,
" code " : " error_http_check_unknown_error " ,
" content " : " an error happen while trying to get your domain, it ' s very likely unreachable " ,
} )
2019-01-19 07:54:11 +01:00
2019-01-19 07:38:13 +01:00
# [x] - get ip
# [x] - get request json
# [x] - in request json get domain target
2019-01-19 08:10:16 +01:00
# [x] - validate domain is in correct format
2019-01-19 07:38:13 +01:00
# [ ] - check dns that domain == ip
# [ ] - if not, complain
2019-01-19 07:54:11 +01:00
# [x] - if everything is ok, try to get with http
# [x] - ADD TIMEOUT
# [x] - try/catch, if everything is ok → response ok
# [x] - otherwise reponse with exception
2019-01-19 08:08:36 +01:00
# [x] - create error codes
# [ ] - rate limit
2019-01-19 07:38:13 +01:00
return json_response ( { " status " : " ok " } )
2019-01-19 07:25:23 +01:00
@app.route ( " / " )
2019-01-19 07:38:13 +01:00
async def main ( request ) :
2019-01-19 07:25:23 +01:00
return html ( " You aren ' t really supposed to use this website using your browser.<br><br>It ' s a small server to check if a YunoHost instance can be reached by http before trying to instal a LE certificate. " )
if __name__ == " __main__ " :
app . run ( host = " 0.0.0.0 " , port = 7000 )