やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

SVGZをブラウザで表示する方法1 Webサーバ編(失敗)

 SVGは表示できるけど、SVGZは表示できない。そこで方法を調査した。残念ながら今回は失敗した記録である。

SVGZをブラウザで表示する方法

 SVGZはSVGGzip圧縮しただけなので、それを展開してSVGで返却してやれば表示可能なはず。そのための機能をサーバかクライアントで実装すればいいはず。

  1. Webサーバを自作する
    1. Apatch
    2. Python
  2. クライアントで展開する
    1. CompressionStream API

1. Webサーバを自作する

1. Apatch

 ググったら出てくる方法。

 WebサーバアプリApatch上で.htaccessファイルを配置し、以下内容を追記する。

AddType image/svg+xml .svg .svgz
AddEncoding gzip .svgz

 ただ、私はApatchサーバを作ったことがないので、それ以前に何をどうすればいいかサッパリ判らない。いきなり上記のようなことを言われてもまるで判らない。

2. Python

 前回PythonHTTPSローカルサーバを立てた。これをそのまま使えば表示できるかも? と思ったがダメだった。

 おそらく拡張子svgzファイルをgzip展開して返却するような機能をサーバに実装すれば表示できるようになるだろうが、それをPythonコードでどう実装すればいいのかサッパリ判らない。

 流石にPythonやそのライブラリから勉強し直すのは避けたい。私はただSVGZを表示して欲しいだけなのだから。一応、少しだけコードを書いて試行錯誤したがダメだった。

1. extensions_map

 前回のサーバに以下を挿入した。

Handler.extensions_map['.svgz'] = 'image/svg+xml'

 他にも以下のようなパターンを試してみた。

Handler.extensions_map['.svgz'] = 'image/svg+xml;Content-Encoding=gzip;'
Handler.extensions_map['.svgz'] = 'image/svg+xml;charset=UTF-8;Content-Encoding=gzip;'

 が、ダメだった。SVGZファイルを参照する<img>タグで画像が表示されなかった。念の為、全体のコードを掲載しておく。

run_server.py

import ssl
from http.server import HTTPServer, SimpleHTTPRequestHandler

PORT = 443
CERTFILE = "./localhost.pem"

Handler = SimpleHTTPRequestHandler
Handler.extensions_map['.svgz'] = 'image/svg+xml;charset=UTF-8;Content-Encoding=gzip;'

context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(CERTFILE)

with HTTPServer(("", PORT), Handler) as httpd:
    print("serving at address", httpd.server_address, "using cert file", CERTFILE)
    httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
    httpd.serve_forever()
2. SimpleHTTPRequestHandler

 SimpleHTTPRequestHandlerPythonでHTTPサーバを作る時のクラス。前回コードでもこれを使った。これを改造してSVGZのときはSVGに変換して返すように実装すればいいはず。

 私はサーバの知識がまったくない。でも、適当にググってコードを書いてみた。

import os.path
import zlib
import urllib
from http.server import SimpleHTTPRequestHandler
#https://github.com/ksmith97/GzipSimpleHTTPServer/blob/master/GzipSimpleHTTPServer.py#L85
class SvgzHTTPRequestHandler(SimpleHTTPRequestHandler):
    def do_GET(self):
        # 拡張子が.svgzならGzip展開する
        path = self.translate_path(self.path)
        if 'svgz' == os.path.splitext(path):
            with urllib.request.urlopen(path) as f:
                dec = gzip.GzipFile(fileobj=f)
                svg = dec.read().decode("utf-8")
                self.send_header("Content-length", str(len(str(svg))))
                self.send_header("Content-Type", "image/svg+xml")
                self.end_headers()
                self.wfile.write(svg)
                self.wfile.flush()
        else:
            super.do_GET()
        
    def translate_path(self, path):
        path = path.split('?',1)[0]
        path = path.split('#',1)[0]
        path = posixpath.normpath(urllib.unquote(path))
        words = path.split('/')
        words = filter(None, words)
        path = os.getcwd()
        for word in words:
            drive, word = os.path.splitdrive(word)
            head, word = os.path.split(word)
            if word in (os.curdir, os.pardir): continue
            path = os.path.join(path, word)
        return path

 前回のスクリプトで起動し、ブラウザで警告を解除したが、サーバ起動に失敗したようで以下ログが端末に表示された。

----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 44652)
Traceback (most recent call last):
  File "/usr/lib/python3.7/socketserver.py", line 316, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python3.7/socketserver.py", line 347, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python3.7/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
TypeError: 'module' object is not callable
----------------------------------------

 ググったら書き込みの所で出るエラーらしい。self.wfile.write(svg)の所だと思う。でも、サーバの仕組みを理解していないので、これ以上は読み取れなかった。

 ぶっちゃけ何してるか判らずコードをコピペしただけという感じ。

 私の技術力ではサーバ側からのアプローチはこれが限界。

 これら失敗コードは以下リポジトリにアップした。

感想

 ググっても今回の要件にピッタリのコードが無い。ニッチすぎるのか? かといって私の知識が足りなすぎてコードが書けない。

 ネットで関係ありそうなコードを見ても、自分がやりたいことと関係あるのか、どう応用すればやりたいことを実装できるのか判らない。公式ドキュメントでAPI学習からはじめるのは気が遠くなってやる気にならない。そもそもサーバの概念やPythonの基本構文なんかも前提知識なので学習に時間かかる。

 SVGZを表示したいだけなのに、なんでWebサーバやPythonの勉強しなきゃいけないの? 本当にサーバ必要なの? バカなの? とか思って萎える。

 誰か助けて。できれば要件を満たす最小コードを書いて教えてください。

 きっと無理だろうから自分でやろう。自分のバカさは自分で補うしかないんだ。次はアプローチを変えよう。気分を変えよう。脳ごと変えたい。

次回

 投稿は明日までお待ちを。約束された成功に乞うご期待。