summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorEd Tanous <ed.tanous@intel.com>2017-04-04 17:23:00 -0700
committerEd Tanous <ed.tanous@intel.com>2017-04-04 17:23:00 -0700
commitb4a7bfad0a3ded7a813bdb44a46383316dc49b24 (patch)
treeabb214b5a886744e942257641c2b60f7d97e4f15 /scripts
parent1e94fa402ac5858329101e448593a0b61d24f765 (diff)
downloadbmcweb-b4a7bfad0a3ded7a813bdb44a46383316dc49b24.tar.gz
bmcweb-b4a7bfad0a3ded7a813bdb44a46383316dc49b24.zip
Add route printer
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/build_web_assets.py242
1 files changed, 130 insertions, 112 deletions
diff --git a/scripts/build_web_assets.py b/scripts/build_web_assets.py
index 0521bd7..d820c5a 100755
--- a/scripts/build_web_assets.py
+++ b/scripts/build_web_assets.py
@@ -5,6 +5,7 @@ import os
import gzip
import hashlib
from subprocess import Popen, PIPE
+from collections import defaultdict
import re
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
@@ -20,59 +21,37 @@ CONTENT_TYPES = {
'.woff': "application/x-font-woff",
}
-CPP_BEGIN_BUFFER = """
-#include <webassets.hpp>
-
-"""
+CPP_MIDDLE_BUFFER = """ CROW_ROUTE(app, "{relative_path_sha1}")
+ ([](const crow::request& req, crow::response& res) {{
+ {CACHE_FOREVER_HEADER}
+ res.add_header("ETag", "{sha1}");
+ if (req.headers.count("If-None-Match") == 1) {{
+ if (req.get_header_value("If-None-Match") == "{sha1}") {{
+ res.code = 304;
+ res.end();
+ return;
+ }}
+ }}
-ROUTE_DECLARATION = """
+ res.code = 200;
+ // TODO, if you have a browser from the dark ages that doesn't support gzip,
+ // unzip it before sending based on Accept-Encoding header
+ res.add_header("Content-Encoding", "{content_encoding}");
+ res.add_header("Content-Type", "{content_type}");
-void crow::webassets::request_routes(BmcAppType& app){
-"""
+ res.write(staticassets::{relative_path_escaped});
-CACHE_FOREVER_HEADER = """
- res.add_header("Cache-Control", "public, max-age=31556926");
-"""
-
-CPP_MIDDLE_BUFFER = """
- CROW_ROUTE(app, "{relative_path_sha1}")([](const crow::request& req, crow::response& res) {{
- {CACHE_FOREVER_HEADER}
-
- res.add_header("ETag", "{sha1}");
- if (req.headers.count("If-None-Match") == 1) {{
- if (req.get_header_value("If-None-Match") == "{sha1}"){{
- res.code = 304;
- res.end();
- return;
- }}
- }}
-
- res.code = 200;
- // TODO, if you have a browser from the dark ages that doesn't support gzip,
- // unzip it before sending based on Accept-Encoding header
- res.add_header("Content-Encoding", "{content_encoding}");
- res.add_header("Content-Type", "{content_type}");
-
- res.write({relative_path_escaped});
-
- res.end();
- }});
+ res.end();
+ }});
"""
def twos_comp(val, bits):
"""compute the 2's compliment of int value val"""
- if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255
+ if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255
val = val - (1 << bits) # compute negative value
return val # return positive value as is
-CPP_END_BUFFER = """
-}
-"""
-
-CPP_END_BUFFER2 = """const static std::string {relative_path_escaped}{{{file_bytes}}};
-"""
-
def get_relative_path(full_filepath):
pathsplit = full_filepath.split(os.path.sep)
relative_path = os.path.sep.join(pathsplit[pathsplit.index("static") + 1:])
@@ -85,6 +64,7 @@ def get_relative_path(full_filepath):
return relative_path, relative_path_escaped
+
def get_sha1_path_from_relative(relative_path, sha1):
if sha1 != "":
path, extension = os.path.splitext(relative_path)
@@ -92,11 +72,13 @@ def get_sha1_path_from_relative(relative_path, sha1):
else:
return relative_path
+
def filter_html(sha1_list, file_content):
string_content = file_content.decode()
for key, value in sha1_list.items():
replace_name = get_sha1_path_from_relative(key, value)
- string_content_new = re.sub("((src|href)=[\"'])(" + re.escape(key) + ")([\"'])", "\\1" + replace_name + "\\4", string_content)
+ string_content_new = re.sub(
+ "((src|href)=[\"'])(" + re.escape(key) + ")([\"'])", "\\1" + replace_name + "\\4", string_content)
if string_content_new != string_content:
print(" Replaced {}".format(key))
print(" With {}".format(replace_name))
@@ -104,6 +86,7 @@ def filter_html(sha1_list, file_content):
return string_content.encode()
+
def filter_js(sha1_list, file_content):
string_content = file_content.decode()
@@ -117,23 +100,13 @@ def filter_js(sha1_list, file_content):
string_content = string_content_new
return string_content.encode()
+
def compute_sha1_and_update_dict(sha1_list, file_content, relative_path):
sha = hashlib.sha1()
sha.update(file_content)
- sha_bytes = sha.digest()
-
- sha_text = "".join("{:02x}".format(x) for x in sha_bytes)
+ sha_text = sha.hexdigest()
sha1_list[relative_path] = sha_text
-FILE_PRECIDENCE = ['.woff', '.png' ,'.css', '.js', '.html']
-def sort_order(full_filepath):
- # sort list based on users
- path, ext = os.path.splitext(full_filepath)
- if ext in FILE_PRECIDENCE:
- return FILE_PRECIDENCE.index(ext) + 1
- else:
- return 0
-
def get_dependencies(dependency_list, full_filepath):
r = []
@@ -145,11 +118,13 @@ def get_dependencies(dependency_list, full_filepath):
r.extend(sub_deps)
return r
+
def remove_duplicates_preserve_order(seq):
seen = set()
seen_add = seen.add
return [x for x in seq if not (x in seen or seen_add(x))]
+
def main():
""" Main Function """
@@ -164,11 +139,12 @@ def main():
file_list = [os.path.realpath(f) for f in file_list]
sha1_list = {}
+ content_dict = {}
- file_list.sort(key=sort_order)
- from collections import defaultdict
depends_on = {}
+ gzip_content = not(args.debug)
+
for full_filepath in file_list:
relative_path, relative_path_escaped = get_relative_path(full_filepath)
text_file_types = ['.css', '.js', '.html']
@@ -180,12 +156,14 @@ def main():
for full_replacename in file_list:
relative_replacename, _ = get_relative_path(full_replacename)
if ext == ".html":
- match = re.search("((src|href)=[\"'])(" + relative_replacename + ")([\"'])", file_content)
+ match = re.search(
+ "((src|href)=[\"'])(" + relative_replacename + ")([\"'])", file_content)
if match:
depends_on[full_filepath].append(full_replacename)
elif ext == ".js" or ext == ".css":
- match = re.search("([\"'](\.\./)*)(" + relative_replacename + ")([\"'\?])", file_content)
+ match = re.search(
+ "([\"'](\.\./)*)(" + relative_replacename + ")([\"'\?])", file_content)
if match:
depends_on[full_filepath].append(full_replacename)
@@ -196,52 +174,70 @@ def main():
dependency_ordered_file_list.extend(deps)
dependency_ordered_file_list.append(full_filepath)
- dependency_ordered_file_list = remove_duplicates_preserve_order(dependency_ordered_file_list)
-
- with open(args.output, 'w') as cpp_output:
- cpp_output.write(CPP_BEGIN_BUFFER)
-
+ dependency_ordered_file_list = remove_duplicates_preserve_order(
+ dependency_ordered_file_list)
+
+
+ for full_filepath in dependency_ordered_file_list:
+ # make sure none of the files are hidden
+ with open(full_filepath, 'rb') as input_file:
+ file_content = input_file.read()
+ relative_path, relative_path_escaped = get_relative_path(
+ full_filepath)
+ extension = os.path.splitext(relative_path)[1]
+
+ print("Including {:<40} size {:>7}".format(
+ relative_path, len(file_content)))
+
+ if extension == ".html" or relative_path == "/":
+ new_file_content = filter_html(sha1_list, file_content)
+ elif extension == ".js" or extension == ".css":
+ new_file_content = filter_js(sha1_list, file_content)
+ else:
+ new_file_content = file_content
+
+ file_content = new_file_content
+
+ if gzip_content:
+ file_content = gzip.compress(file_content)
+
+ compute_sha1_and_update_dict(
+ sha1_list, file_content, relative_path)
+ content_dict[full_filepath] = file_content
+
+ with open(args.output.replace("cpp", "hpp"), 'w') as hpp_output:
+ hpp_output.write("#pragma once\n"
+ "\n"
+ "#include <string>\n"
+ "\n"
+ "#include <crow/app.h>\n"
+ "#include <crow/http_request.h>\n"
+ "#include <crow/http_response.h>\n"
+ "\n"
+ "#include <crow/routing.h>\n"
+ "#include <crow/bmc_app_type.hpp>\n"
+ "\n"
+ "namespace crow {\n"
+ "namespace webassets {\n"
+ )
+
+ hpp_output.write("struct staticassets {\n")
for full_filepath in dependency_ordered_file_list:
- # make sure none of the files are hidden
- with open(full_filepath, 'rb') as input_file:
- file_content = input_file.read()
- relative_path, relative_path_escaped = get_relative_path(full_filepath)
- extension = os.path.splitext(relative_path)[1]
-
- print("Including {:<40} size {:>7}".format(relative_path, len(file_content)))
-
- if extension == ".html" or relative_path == "/":
- new_file_content = filter_html(sha1_list, file_content)
- elif extension == ".js" or extension == ".css":
- new_file_content = filter_js(sha1_list, file_content)
- else:
- new_file_content = file_content
-
- file_content = new_file_content
-
- if not args.debug:
- file_content = gzip.compress(file_content)
- #file_content = file_content[:10]
- # compute the 2s complement. If you don't, you get narrowing warnings from gcc/clang
-
- compute_sha1_and_update_dict(sha1_list, file_content, relative_path)
- array_binary_text = ', '.join(str(twos_comp(x, 8)) for x in file_content)
-
- cpp_output.write(
- CPP_END_BUFFER2.format(
- relative_path=relative_path,
- file_bytes=array_binary_text,
- relative_path_escaped=relative_path_escaped
- )
- )
-
- cpp_output.write(ROUTE_DECLARATION)
+ relative_path, relative_path_escaped = get_relative_path(
+ full_filepath)
+ hpp_output.write(
+ " static const std::string {};\n".format(relative_path_escaped))
+ hpp_output.write("};\n\n")
+ hpp_output.write("template <typename... Middlewares>\n")
+ hpp_output.write("void request_routes(Crow<Middlewares...>& app) {\n")
for full_filepath in dependency_ordered_file_list:
- relative_path, relative_path_escaped = get_relative_path(full_filepath)
+ relative_path, relative_path_escaped = get_relative_path(
+ full_filepath)
sha1 = sha1_list.get(relative_path, '')
- content_type = CONTENT_TYPES.get(os.path.splitext(relative_path)[1], "")
+ content_type = CONTENT_TYPES.get(
+ os.path.splitext(relative_path)[1], "")
if content_type == "":
print("unknown content type for {}".format(relative_path))
@@ -250,34 +246,56 @@ def main():
relative_path = "/"
relative_path_sha1 = "/"
else:
- relative_path_sha1 = "/" + get_sha1_path_from_relative(relative_path, sha1)
-
- content_encoding = 'none' if args.debug else 'gzip'
+ relative_path_sha1 = "/" + \
+ get_sha1_path_from_relative(relative_path, sha1)
+ #print("relative_path_sha1: " + relative_path_sha1)
+ #print("sha1: " + sha1)
+ content_encoding = 'gzip' if gzip_content else 'none'
environment = {
- 'relative_path':relative_path,
+ 'relative_path': relative_path,
'relative_path_escaped': relative_path_escaped,
'relative_path_sha1': relative_path_sha1,
'sha1': sha1,
'sha1_short': sha1[:20],
'content_type': content_type,
- 'content_encoding': content_encoding
+ 'content_encoding': content_encoding,
+ "CACHE_FOREVER_HEADER": ""
}
- environment["CACHE_FOREVER_HEADER"] = ""
+
if ENABLE_CACHING:
# if we have a valid sha1, and we have a unique path to the resource
# it can be safely cached forever
if sha1 != "" and relative_path != relative_path_sha1:
- environment["CACHE_FOREVER_HEADER"] = CACHE_FOREVER_HEADER
+ environment["CACHE_FOREVER_HEADER"] = "res.add_header(\"Cache-Control\", \"public, max-age=31556926\");\n"
- content = CPP_MIDDLE_BUFFER.format(
- **environment
- )
- cpp_output.write(content)
+ content = CPP_MIDDLE_BUFFER.format(**environment)
+ hpp_output.write(content)
- cpp_output.write(CPP_END_BUFFER)
+ hpp_output.write("}\n}\n}")
+ with open(args.output, 'w') as cpp_output:
+ cpp_output.write("#include <webassets.hpp>\n"
+ "namespace crow{\n"
+ "namespace webassets{\n")
+ for full_filepath in dependency_ordered_file_list:
+ file_content = content_dict[full_filepath]
+ relative_path, relative_path_escaped = get_relative_path(
+ full_filepath)
+ # compute the 2s complement for negative numbers.
+ # If you don't, you get narrowing warnings from gcc/clang
+ array_binary_text = ', '.join(str(twos_comp(x, 8))
+ for x in file_content)
+ cpp_end_buffer = "const std::string staticassets::{relative_path_escaped}{{{file_bytes}}};\n"
+ cpp_output.write(
+ cpp_end_buffer.format(
+ relative_path=relative_path,
+ file_bytes=array_binary_text,
+ relative_path_escaped=relative_path_escaped
+ )
+ )
+ cpp_output.write("}\n}\n")
if __name__ == "__main__":
main()
OpenPOWER on IntegriCloud