diff options
| author | Ed Tanous <ed.tanous@intel.com> | 2017-04-04 17:23:00 -0700 |
|---|---|---|
| committer | Ed Tanous <ed.tanous@intel.com> | 2017-04-04 17:23:00 -0700 |
| commit | b4a7bfad0a3ded7a813bdb44a46383316dc49b24 (patch) | |
| tree | abb214b5a886744e942257641c2b60f7d97e4f15 /scripts | |
| parent | 1e94fa402ac5858329101e448593a0b61d24f765 (diff) | |
| download | bmcweb-b4a7bfad0a3ded7a813bdb44a46383316dc49b24.tar.gz bmcweb-b4a7bfad0a3ded7a813bdb44a46383316dc49b24.zip | |
Add route printer
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/build_web_assets.py | 242 |
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() |

