Move symbol static to /symbols

This commit is contained in:
Julien Duponchelle 2016-06-28 18:17:48 +02:00
parent c5fa699b9e
commit 5b4e668eb5
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8
8 changed files with 67 additions and 106 deletions

View File

@ -40,9 +40,10 @@ class Symbols:
'symbol_id': symbol_id,
'filename': file,
'builtin': True,
'url': '/static/builtin_symbols/' + file
})
self._symbols_path[symbol_id] = os.path.join(get_resource("symbols"), file)
symbols.sort(key=lambda x: x["filename"])
#TODO: support ~/GNS3/symbols directory
return symbols

View File

@ -16,7 +16,6 @@
from gns3server.handlers.index_handler import IndexHandler
from gns3server.handlers.static_handler import StaticHandler
from gns3server.handlers.api.controller import *

View File

@ -36,3 +36,17 @@ class SymbolHandler:
controller = Controller.instance()
response.json(controller.symbols.list())
@Route.get(
r"/symbols/{symbol_id:.+}/raw",
description="Get the symbol file",
status_codes={
200: "Symbol returned"
})
def raw(request, response):
controller = Controller.instance()
try:
yield from response.file(controller.symbols.get_path(request.match_info["symbol_id"]))
except KeyError:
response.set_status(404)

View File

@ -1,66 +0,0 @@
#
# Copyright (C) 2016 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import asyncio
import mimetypes
from aiohttp import hdrs
from gns3server.web.route import Route
from gns3server.utils.get_resource import get_resource
class StaticHandler:
@Route.get(
r"/static/{type}/{path:.+}",
description="Serve static content from various locations"
)
def get(request, response):
type = request.match_info["type"]
# CLeanup the path for security
path = os.path.normpath(request.match_info["path"]).strip('/.')
if type == "builtin_symbols":
try:
yield from StaticHandler._serve_file(os.path.join(get_resource("symbols"), path), request, response)
except OSError:
response.set_status(404)
@asyncio.coroutine
def _serve_file(path, request, response):
ct, encoding = mimetypes.guess_type(path)
if not ct:
ct = 'application/octet-stream'
if encoding:
response.headers[hdrs.CONTENT_ENCODING] = encoding
response.content_type = ct
st = os.stat(path)
response.last_modified = st.st_mtime
response.content_length = st.st_size
with open(path, 'rb') as fobj:
response.start(request)
chunk_size = 4096
chunk = fobj.read(chunk_size)
while chunk:
response.write(chunk)
yield from response.drain()
chunk = fobj.read(chunk_size)
if chunk:
response.write(chunk[:count])
yield from response.drain()

View File

@ -17,11 +17,14 @@
import json
import jsonschema
import aiohttp
import aiohttp.web
import mimetypes
import asyncio
import logging
import sys
import jinja2
import sys
import os
from ..utils.get_resource import get_resource
from ..version import __version__
@ -102,6 +105,35 @@ class Response(aiohttp.web.Response):
raise aiohttp.web.HTTPBadRequest(text="{}".format(e))
self.body = json.dumps(answer, indent=4, sort_keys=True).encode('utf-8')
@asyncio.coroutine
def file(self, path):
"""
Return a file as a response
"""
ct, encoding = mimetypes.guess_type(path)
if not ct:
ct = 'application/octet-stream'
if encoding:
self.headers[aiohttp.hdrs.CONTENT_ENCODING] = encoding
self.content_type = ct
st = os.stat(path)
self.last_modified = st.st_mtime
self.content_length = st.st_size
with open(path, 'rb') as fobj:
self.start(self._request)
chunk_size = 4096
chunk = fobj.read(chunk_size)
while chunk:
self.write(chunk)
yield from self.drain()
chunk = fobj.read(chunk_size)
if chunk:
self.write(chunk[:count])
yield from self.drain()
def redirect(self, url):
"""
Redirect to url

View File

@ -26,8 +26,12 @@ def test_list():
symbols = Symbols()
assert {
'symbol_id': ':/symbols/firewall.svg',
'url': '/static/builtin_symbols/firewall.svg',
'filename': 'firewall.svg',
'builtin': True
} in symbols.list()
assert symbols
def test_get_path():
symbols = Symbols()
assert symbols.get_path(':/symbols/firewall.svg') == get_resource("symbols/firewall.svg")

View File

@ -15,6 +15,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import urllib.parse
from gns3server.config import Config
@ -23,7 +25,17 @@ def test_symbols(http_controller):
assert response.status == 200
assert {
'symbol_id': ':/symbols/firewall.svg',
'url': '/static/builtin_symbols/firewall.svg',
'filename': 'firewall.svg',
'builtin': True
} in response.json
def test_get(http_controller):
response = http_controller.get('/symbols/' + urllib.parse.quote(':/symbols/firewall.svg') + '/raw')
assert response.status == 200
assert response.headers['CONTENT-LENGTH'] == '9381'
assert response.headers['CONTENT-TYPE'] == 'image/svg+xml'
assert '</svg>' in response.html
response = http_controller.get('/symbols/404.png/raw')
assert response.status == 404

View File

@ -1,35 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import aiohttp
import os
from unittest.mock import patch
def test_get(http_root):
response = http_root.get('/static/builtin_symbols/firewall.svg')
assert response.status == 200
assert response.headers['CONTENT-LENGTH'] == '9381'
assert response.headers['CONTENT-TYPE'] == 'image/svg+xml'
assert '</svg>' in response.html
response = http_root.get('/static/builtin_symbols/../main.py')
assert response.status == 404
response = http_root.get('/static/builtin_symbols/404.png')
assert response.status == 404