PCEtLXtzdWJ0ZW1wbGF0ZSBjb21tb24vaGVhZGVyX2NvbW1vbn0tLT4JPCEtLXtpZiAkX0dFVFsnbW9kJ10gPT0gJ3ZpZXd0aHJlYWQnICYmICFlbXB0eSgkX0dbJ3RpZCddKX0tLT4KCTxsaW5rIHJlbD0iY2Fub25pY2FsIiBocmVmPSJodHRwczovL3d3dy5xaWRhbzEyMy5jb20vYmJzL3RocmVhZC17JF9HWyd0aWQnXX0tMS0xLmh0bWwiIC8+Cgk8IS0te2Vsc2VpZiAkX0dFVFsnbW9kJ10gPT0gJ2ZvcnVtZGlzcGxheScgJiYgIWVtcHR5KCRfR1snZmlkJ10pfS0tPgoJPGxpbmsgcmVsPSJjYW5vbmljYWwiIGhyZWY9Imh0dHBzOi8vd3d3LnFpZGFvMTIzLmNvbS9iYnMvZm9ydW0teyRfR1snZmlkJ119LTEuaHRtbCIgLz4KCTwhLS17ZWxzZWlmICRfR0VUWydtb2QnXSA9PSAnZ3VpZGUnfS0tPgoJPGxpbmsgcmVsPSJjYW5vbmljYWwiIGhyZWY9Imh0dHBzOi8vd3d3LnFpZGFvMTIzLmNvbS9iYnMvZ3VpZGUvIiAvPgoJPCEtLXtlbHNlaWYgJF9HWydiYXNlc2NyaXB0J10gPT0gJ2ZvcnVtJyAmJiAoZW1wdHkoJF9HRVRbJ21vZCddKSB8fCAkX0dFVFsnbW9kJ10gPT0gJ2luZGV4Jyl9LS0+Cgk8bGluayByZWw9ImNhbm9uaWNhbCIgaHJlZj0iaHR0cHM6Ly93d3cucWlkYW8xMjMuY29tL2Jicy8iIC8+Cgk8IS0tey9pZn0tLT4KCXJgbmB0PG1ldGEgbmFtZT0iYXBwbGljYXRpb24tbmFtZSIgY29udGVudD0iJF9HWydzZXR0aW5nJ11bJ2JibmFtZSddIiAvPgoJPG1ldGEgbmFtZT0ibXNhcHBsaWNhdGlvbi10b29sdGlwIiBjb250ZW50PSIkX0dbJ3NldHRpbmcnXVsnYmJuYW1lJ10iIC8+Cgk8IS0te2lmICRfR1snc2V0dGluZyddWydwb3J0YWxzdGF0dXMnXX0tLT48bWV0YSBuYW1lPSJtc2FwcGxpY2F0aW9uLXRhc2siIGNvbnRlbnQ9Im5hbWU9JF9HWydzZXR0aW5nJ11bJ25hdnMnXVsxXVsnbmF2bmFtZSddO2FjdGlvbi11cmk9e2VjaG8gIWVtcHR5KCRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ3BvcnRhbCddKSA/ICRfR1snc2NoZW1lJ10uJzovLycuJF9HWydzZXR0aW5nJ11bJ2RvbWFpbiddWydhcHAnXVsncG9ydGFsJ10gOiAkX0dbc2l0ZXVybF0uJ3BvcnRhbC5waHAnfTtpY29uLXVyaT17JF9HW3NpdGV1cmxdfXtJTUdESVJ9L3BvcnRhbC5pY28iIC8+PCEtLXsvaWZ9LS0+Cgk8bWV0YSBuYW1lPSJtc2FwcGxpY2F0aW9uLXRhc2siIGNvbnRlbnQ9Im5hbWU9JF9HWydzZXR0aW5nJ11bJ25hdnMnXVsyXVsnbmF2bmFtZSddO2FjdGlvbi11cmk9e2VjaG8gIWVtcHR5KCRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ2ZvcnVtJ10pID8gJF9HWydzY2hlbWUnXS4nOi8vJy4kX0dbJ3NldHRpbmcnXVsnZG9tYWluJ11bJ2FwcCddWydmb3J1bSddIDogJF9HW3NpdGV1cmxdLidmb3J1bS5waHAnfTtpY29uLXVyaT17JF9HW3NpdGV1cmxdfXtJTUdESVJ9L2Jicy5pY28iIC8+Cgk8IS0te2lmICRfR1snc2V0dGluZyddWydncm91cHN0YXR1cyddfS0tPjxtZXRhIG5hbWU9Im1zYXBwbGljYXRpb24tdGFzayIgY29udGVudD0ibmFtZT0kX0dbJ3NldHRpbmcnXVsnbmF2cyddWzNdWyduYXZuYW1lJ107YWN0aW9uLXVyaT17ZWNobyAhZW1wdHkoJF9HWydzZXR0aW5nJ11bJ2RvbWFpbiddWydhcHAnXVsnZ3JvdXAnXSkgPyAkX0dbJ3NjaGVtZSddLic6Ly8nLiRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ2dyb3VwJ10gOiAkX0dbc2l0ZXVybF0uJ2dyb3VwLnBocCd9O2ljb24tdXJpPXskX0dbc2l0ZXVybF19e0lNR0RJUn0vZ3JvdXAuaWNvIiAvPjwhLS17L2lmfS0tPgoJPCEtLXtpZiBoZWxwZXJfYWNjZXNzOjpjaGVja19tb2R1bGUoJ2ZlZWQnKX0tLT48bWV0YSBuYW1lPSJtc2FwcGxpY2F0aW9uLXRhc2siIGNvbnRlbnQ9Im5hbWU9JF9HWydzZXR0aW5nJ11bJ25hdnMnXVs0XVsnbmF2bmFtZSddO2FjdGlvbi11cmk9e2VjaG8gIWVtcHR5KCRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ2hvbWUnXSkgPyAkX0dbJ3NjaGVtZSddLic6Ly8nLiRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ2hvbWUnXSA6ICRfR1tzaXRldXJsXS4naG9tZS5waHAnfTtpY29uLXVyaT17JF9HW3NpdGV1cmxdfXtJTUdESVJ9L2hvbWUuaWNvIiAvPjwhLS17L2lmfS0tPgoJPCEtLXtpZiAkX0dbJ2Jhc2VzY3JpcHQnXSA9PSAnZm9ydW0nICYmICRfR1snc2V0dGluZyddWydhcmNoaXZlciddfS0tPgoJCTxsaW5rIHJlbD0iYXJjaGl2ZXMiIHRpdGxlPSIkX0dbJ3NldHRpbmcnXVsnYmJuYW1lJ10iIGhyZWY9InskX0dbc2l0ZXVybF19YXJjaGl2ZXIvIiAvPgoJPCEtLXsvaWZ9LS0+Cgk8IS0te2lmICFlbXB0eSgkcnNzaGVhZCl9LS0+JHJzc2hlYWQ8IS0tey9pZn0tLT4KCTwhLS17aWYgd2lkdGhhdXRvKCl9LS0+CgkJPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBpZD0iY3NzX3dpZHRoYXV0byIgdHlwZT0idGV4dC9jc3MiIGhyZWY9J3skX0dbJ3NldHRpbmcnXVsnY3NzcGF0aCddfXtTVFlMRUlEfV93aWR0aGF1dG8uY3NzP3tWRVJIQVNIfScgLz4KCQk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+SFRNTE5PREUuY2xhc3NOYW1lICs9ICcgd2lkdGhhdXRvJzwvc2NyaXB0PgoJPCEtLXsvaWZ9LS0+Cgk8IS0te2lmICRfR1snYmFzZXNjcmlwdCddID09ICdmb3J1bScgfHwgJF9HWydiYXNlc2NyaXB0J10gPT0gJ2dyb3VwJ30tLT4KCQk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJ7JF9HW3NldHRpbmddW2pzcGF0aF19Zm9ydW0uanM/e1ZFUkhBU0h9Ij48L3NjcmlwdD4KCTwhLS17ZWxzZWlmICRfR1snYmFzZXNjcmlwdCddID09ICdob21lJ30tLT4KCQk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJ7JF9HW3NldHRpbmddW2pzcGF0aF19aG9tZS5qcz97VkVSSEFTSH0iPjwvc2NyaXB0PgoJPCEtLXtlbHNlaWYgJF9HWydiYXNlc2NyaXB0J10gPT0gJ3BvcnRhbCd9LS0+CgkJPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ieyRfR1tzZXR0aW5nXVtqc3BhdGhdfXBvcnRhbC5qcz97VkVSSEFTSH0iPjwvc2NyaXB0PgoJPCEtLXsvaWZ9LS0+Cgk8IS0te2lmICRfR1snYmFzZXNjcmlwdCddICE9ICdwb3J0YWwnICYmICRfR0VUWydkaXknXSA9PSAneWVzJyAmJiBjaGVja19kaXlfcGVybSgkdG9waWMpfS0tPgoJCTxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9InskX0dbc2V0dGluZ11banNwYXRoXX1wb3J0YWwuanM/e1ZFUkhBU0h9Ij48L3NjcmlwdD4KCTwhLS17L2lmfS0tPgoJPCEtLXtpZiAkX0dFVFsnZGl5J10gPT0gJ3llcycgJiYgY2hlY2tfZGl5X3Blcm0oJHRvcGljKX0tLT4KCQk8bGluayByZWw9InN0eWxlc2hlZXQiIHR5cGU9InRleHQvY3NzIiBpZD0iZGl5X2NvbW1vbiIgaHJlZj0ieyRfR1snc2V0dGluZyddWydjc3NwYXRoJ119e1NUWUxFSUR9X2Nzc19kaXkuY3NzP3tWRVJIQVNIfSIgLz4KCTwhLS17L2lmfS0tPgo8L2hlYWQ+Cgo8Ym9keSBpZD0ibnZfeyRfR1tiYXNlc2NyaXB0XX0iIGNsYXNzPSJwZ197Q1VSTU9EVUxFfXtpZiAkX0dbJ2Jhc2VzY3JpcHQnXSA9PT0gJ3BvcnRhbCcgJiYgQ1VSTU9EVUxFID09PSAnbGlzdCcgJiYgIWVtcHR5KCRjYXQpfSB7JGNhdFsnYm9keWNzcyddfXsvaWZ9IiBvbmtleWRvd249ImlmKGV2ZW50LmtleUNvZGU9PTI3KSByZXR1cm4gZmFsc2U7Ij4KCTxkaXYgaWQ9ImFwcGVuZF9wYXJlbnQiPjwvZGl2PjxkaXYgaWQ9ImFqYXh3YWl0aWQiPjwvZGl2PgoJPCEtLXtpZiAkX0dFVFsnZGl5J10gPT0gJ3llcycgJiYgY2hlY2tfZGl5X3Blcm0oJHRvcGljKX0tLT4KCQk8IS0te3RlbXBsYXRlIGNvbW1vbi9oZWFkZXJfZGl5fS0tPgoJPCEtLXsvaWZ9LS0+Cgk8IS0te2lmIGNoZWNrX2RpeV9wZXJtKCR0b3BpYyl9LS0+CgkJPCEtLXt0ZW1wbGF0ZSBjb21tb24vaGVhZGVyX2RpeW5hdn0tLT4KCTwhLS17L2lmfS0tPgoJPCEtLXtpZiBDVVJNT0RVTEUgPT0gJ3RvcGljJyAmJiAkdG9waWMgJiYgZW1wdHkoJHRvcGljWyd1c2VoZWFkZXInXSkgJiYgY2hlY2tfZGl5X3Blcm0oJHRvcGljKX0tLT4KCQkkZGl5bmF2Cgk8IS0tey9pZn0tLT4KCTwhLS17aWYgZW1wdHkoJHRvcGljKSB8fCAkdG9waWNbJ3VzZWhlYWRlciddfS0tPgoJCTwhLS17aWYgJF9HWydzZXR0aW5nJ11bJ21vYmlsZSddWydhbGxvd21vYmlsZSddICYmICghJF9HWydzZXR0aW5nJ11bJ2NhY2hlaW5kZXhsaWZlJ10gJiYgISRfR1snc2V0dGluZyddWydjYWNoZXRocmVhZG9uJ10gfHwgJF9HWyd1aWQnXSkgJiYgKCRfR0VUWydkaXknXSAhPSAneWVzJyB8fCAhJF9HRVRbJ2luYWpheCddKSAmJiAoJF9HWydtb2JpbGUnXSAhPSAnJyAmJiAkX0dbJ2Nvb2tpZSddWydtb2JpbGUnXSA9PSAnJyAmJiAkX0dFVFsnbW9iaWxlJ10gIT0gJ25vJyl9LS0+CgkJCTxkaXYgY2xhc3M9InhpMSBibSBibV9jIj4KCQkJICAgIHtsYW5nIHlvdXJfbW9iaWxlX2Jyb3dzZXJ9PGEgaHJlZj0ieyRfR1snc2l0ZXVybCddfWZvcnVtLnBocD9tb2JpbGU9eWVzIj57bGFuZyBnb190b19tb2JpbGV9PC9hPiA8c3BhbiBjbGFzcz0ieGcxIj58PC9zcGFuPiA8YSBocmVmPSIkX0dbJ3NldHRpbmcnXVsnbW9iaWxlJ11bJ25vbW9iaWxldXJsJ10iPntsYW5nIHRvX2JlX2NvbnRpbnVlfTwvYT4KCQkJPC9kaXY+CgkJPCEtLXsvaWZ9LS0+CgkJPCEtLXtpZiAhZW1wdHkoJF9HWydzZXR0aW5nJ11bJ3Nob3J0Y3V0J10pICYmICRfR1snbWVtYmVyJ11bY3JlZGl0c10gPj0gJF9HWydzZXR0aW5nJ11bJ3Nob3J0Y3V0J119LS0+CgkJCTxkaXYgaWQ9InNob3J0Y3V0Ij4KCQkJCTxzcGFuPjxhIGhyZWY9ImphdmFzY3JpcHQ6OyIgaWQ9InNob3J0Y3V0Y2xvc2VpZCIgdGl0bGU9IntsYW5nIGNsb3NlfSI+e2xhbmcgY2xvc2V9PC9hPjwvc3Bhbj4KCQkJCXtsYW5nIHNob3J0Y3V0X25vdGljZX0KCQkJCTxhIGhyZWY9ImphdmFzY3JpcHQ6OyIgaWQ9InNob3J0Y3V0dGlwIj57bGFuZyBzaG9ydGN1dF9hZGR9PC9hPgoKCQkJPC9kaXY+CgkJCTxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij5zZXRUaW1lb3V0KHNldFNob3J0Y3V0LCAyMDAwKTs8L3NjcmlwdD4KCQk8IS0tey9pZn0tLT4KCQk8ZGl2IGlkPSJ0b3B0YiIgY2xhc3M9ImNsIj4KCQkJPCEtLXtob29rL2dsb2JhbF9jcG5hdl90b3B9LS0+CgkJCTxkaXYgY2xhc3M9IndwIj4KCQkJCTxkaXYgY2xhc3M9InoiPgoJCQkJCTwhLS17bG9vcCAkX0dbJ3NldHRpbmcnXVsndG9wbmF2cyddWzBdICRuYXZ9LS0+CgkJCQkJCTwhLS17aWYgaXNfYXJyYXkoJG5hdikgJiYgJG5hdlsnYXZhaWxhYmxlJ10gJiYgKCEkbmF2WydsZXZlbCddIHx8ICgkbmF2WydsZXZlbCddID09IDEgJiYgJF9HWyd1aWQnXSkgfHwgKCRuYXZbJ2xldmVsJ10gPT0gMiAmJiAkX0dbJ2FkbWluaWQnXSA+IDApIHx8ICgkbmF2WydsZXZlbCddID09IDMgJiYgJF9HWydhZG1pbmlkJ10gPT0gMSkpfS0tPiRuYXZbY29kZV08IS0tey9pZn0tLT4KCQkJCQk8IS0tey9sb29wfS0tPgoJCQkJCTwhLS17aG9vay9nbG9iYWxfY3BuYXZfZXh0cmExfS0tPgoJCQkJPC9kaXY+CgkJCQk8ZGl2IGNsYXNzPSJ5Ij4KCQkJCQk8YSBpZD0ic3dpdGNoYmxpbmQiIGhyZWY9ImphdmFzY3JpcHQ6OyIgb25jbGljaz0idG9nZ2xlQmxpbmQodGhpcykiIHRpdGxlPSJ7bGFuZyBzd2l0Y2hfYmxpbmR9IiBjbGFzcz0ic3dpdGNoYmxpbmQiPjwvYT4KCQkJCQk8IS0te2hvb2svZ2xvYmFsX2NwbmF2X2V4dHJhMn0tLT4KCQkJCQk8IS0te2xvb3AgJF9HWydzZXR0aW5nJ11bJ3RvcG5hdnMnXVsxXSAkbmF2fS0tPgoJCQkJCQk8IS0te2lmIGlzX2FycmF5KCRuYXYpICYmICRuYXZbJ2F2YWlsYWJsZSddICYmICghJG5hdlsnbGV2ZWwnXSB8fCAoJG5hdlsnbGV2ZWwnXSA9PSAxICYmICRfR1sndWlkJ10pIHx8ICgkbmF2WydsZXZlbCddID09IDIgJiYgJF9HWydhZG1pbmlkJ10gPiAwKSB8fCAoJG5hdlsnbGV2ZWwnXSA9PSAzICYmICRfR1snYWRtaW5pZCddID09IDEpKX0tLT4kbmF2W2NvZGVdPCEtLXsvaWZ9LS0+CgkJCQkJPCEtLXsvbG9vcH0tLT4KCQkJCQk8IS0te2lmIGVtcHR5KCRfR1snZGlzYWJsZWR3aWR0aGF1dG8nXSkgJiYgJF9HWydzZXR0aW5nJ11bJ3N3aXRjaHdpZHRoYXV0byddfS0tPgoJCQkJCQk8YSBocmVmPSJqYXZhc2NyaXB0OjsiIGlkPSJzd2l0Y2h3aWR0aCIgb25jbGljaz0id2lkdGhhdXRvKHRoaXMpIiB0aXRsZT0ie2lmIHdpZHRoYXV0bygpfXtsYW5nIHN3aXRjaF9uYXJyb3d9e2Vsc2V9e2xhbmcgc3dpdGNoX3dpZGV9ey9pZn0iIGNsYXNzPSJzd2l0Y2h3aWR0aCI+PCEtLXtpZiB3aWR0aGF1dG8oKX0tLT57bGFuZyBzd2l0Y2hfbmFycm93fTwhLS17ZWxzZX0tLT57bGFuZyBzd2l0Y2hfd2lkZX08IS0tey9pZn0tLT48L2E+CgkJCQkJPCEtLXsvaWZ9LS0+CgkJCQkJPCEtLXtpZiAkX0dbJ3VpZCddICYmICFlbXB0eSgkX0dbJ3N0eWxlJ11bJ2V4dHN0eWxlJ10pfS0tPjxhIGlkPSJzc2xjdCIgaHJlZj0iamF2YXNjcmlwdDo7IiBvbm1vdXNlb3Zlcj0iZGVsYXlTaG93KHRoaXMsIGZ1bmN0aW9uKCkge3Nob3dNZW51KHsnY3RybGlkJzonc3NsY3QnLCdwb3MnOiczNCEnfSl9KTsiPntsYW5nIGNoYW5nZXN0eWxlfTwvYT48IS0tey9pZn0tLT4KCQkJCQk8IS0te2lmIGNoZWNrX2RpeV9wZXJtKCR0b3BpYyl9LS0+CgkJCQkJCSRkaXluYXYKCQkJCQk8IS0tey9pZn0tLT4KCQkJCTwvZGl2PgoJCQk8L2Rpdj4KCQk8L2Rpdj4KCgkJPCEtLXtpZiAhSVNfUk9CT1R9LS0+CgkJCTwhLS17aWYgJF9HWyd1aWQnXSAmJiAhJF9HWydzZXR0aW5nJ11bJ2JiY2xvc2VkJ10gJiYgZW1wdHkoJF9HWydtZW1iZXInXVsnZnJlZXplJ10pICYmICRfR1snbWVtYmVyJ11bJ2dyb3VwaWQnXSAhPSA1fS0tPgoJCQk8dWwgaWQ9Im15cHJvbXB0X21lbnUiIGNsYXNzPSJwX3BvcCIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ij4KCQkJCTxsaT48YSBocmVmPSJob21lLnBocD9tb2Q9c3BhY2UmZG89cG0iIGlkPSJwbV9udGMiIHN0eWxlPSJiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0OyBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAwIDUwJTsiPjxlbSBjbGFzcz0icHJvbXB0X25ld3N7aWYgZW1wdHkoJF9HW21lbWJlcl1bbmV3cG1dKX1fMHsvaWZ9Ij48L2VtPntsYW5nIHBtX2NlbnRlcn08L2E+PC9saT4KCQkJCTwhLS17aWYgJF9HWydzZXR0aW5nJ11bJ2ZvbGxvd3N0YXR1cyddfS0tPgoJCQkJCTxsaT48YSBocmVmPSJob21lLnBocD9tb2Q9Zm9sbG93JmRvPWZvbGxvd2VyIj48ZW0gY2xhc3M9InByb21wdF9mb2xsb3dlcntpZiBlbXB0eSgkX0dbbWVtYmVyXVtuZXdwcm9tcHRfbnVtXVtmb2xsb3dlcl0pfV8wey9pZn0iPjwvZW0+PCEtLXtsYW5nIG5vdGljZV9pbnRlcmFjdGl2ZV9mb2xsb3dlcn0tLT57aWYgJF9HW21lbWJlcl1bbmV3cHJvbXB0X251bV1bZm9sbG93ZXJdfSgkX0dbbWVtYmVyXVtuZXdwcm9tcHRfbnVtXVtmb2xsb3dlcl0pey9pZn08L2E+PC9saT4KCQkJCQk8IS0te2lmICRfR1ttZW1iZXJdW25ld3Byb21wdF0gJiYgJF9HW21lbWJlcl1bbmV3cHJvbXB0X251bV1bZm9sbG93XX0tLT4KCQkJCQkJPGxpPjxhIGhyZWY9ImhvbWUucGhwP21vZD1mb2xsb3ciPjxlbSBjbGFzcz0icHJvbXB0X2NvbmNlcm4iPjwvZW0+PCEtLXtsYW5nIG5vdGljZV9pbnRlcmFjdGl2ZV9mb2xsb3d9LS0+KCRfR1ttZW1iZXJdW25ld3Byb21wdF9udW1dW2ZvbGxvd10pPC9hPjwvbGk+CgkJCQkJPCEtLXsvaWZ9LS0+CgkJCQk8IS0tey9pZn0tLT4KCQkJCTwhLS17aWYgJF9HW21lbWJlcl1bbmV3cHJvbXB0XX0tLT4KCQkJCQk8IS0te2xvb3AgJF9HWydtZW1iZXInXVsnY2F0ZWdvcnlfbnVtJ10gJGtleSAkdmFsfS0tPgoJCQkJCQk8bGk+PGEgaHJlZj0iaG9tZS5waHA/bW9kPXNwYWNlJmRvPW5vdGljZSZ2aWV3PSRrZXkiPjxlbSBjbGFzcz0ibm90aWNlXyRrZXkiPjwvZW0+PCEtLXtlY2hvIGxhbmcoJ3RlbXBsYXRlJywgJ25vdGljZV8nLiRrZXkpfS0tPig8c3BhbiBjbGFzcz0icnEiPiR2YWw8L3NwYW4+KTwvYT48L2xpPgoJCQkJCTwhLS17L2xvb3B9LS0+CgkJCQk8IS0tey9pZn0tLT4KCQkJCTwhLS17aWYgZW1wdHkoJF9HWydjb29raWUnXVsnaWdub3JlX25vdGljZSddKX0tLT4KCQkJCQk8bGkgY2xhc3M9Imlnbm9yZV9ub3RpY2VsaSI+PGEgaHJlZj0iamF2YXNjcmlwdDo7IiBvbmNsaWNrPSJzZXRjb29raWUoJ2lnbm9yZV9ub3RpY2UnLCAxKTtoaWRlTWVudSgnbXlwcm9tcHRfbWVudScpIiB0aXRsZT0ie2xhbmcgdGVtcG9yYXJpbHlfdG9fcmVtaW5kfSI+PGVtIGNsYXNzPSJpZ25vcmVfbm90aWNlIj48L2VtPjwvYT48L2xpPgoJCQkJPCEtLXsvaWZ9LS0+CgkJCTwvdWw+CgkJCTwhLS17L2lmfS0tPgoJCQk8IS0te2lmICRfR1sndWlkJ10gJiYgIWVtcHR5KCRfR1snc3R5bGUnXVsnZXh0c3R5bGUnXSl9LS0+CgkJCQk8ZGl2IGlkPSJzc2xjdF9tZW51IiBjbGFzcz0iY2wgcF9wb3AiIHN0eWxlPSJkaXNwbGF5OiBub25lOyI+CgkJCQkJPCEtLXtpZiAhJF9HW3N0eWxlXVtkZWZhdWx0ZXh0c3R5bGVdfS0tPjxzcGFuIGNsYXNzPSJzc2xjdF9idG4iIG9uY2xpY2s9ImV4dHN0eWxlKCcnKSIgdGl0bGU9IntsYW5nIGRlZmF1bHR9Ij48aT48L2k+PC9zcGFuPjwhLS17L2lmfS0tPgoJCQkJCTwhLS17bG9vcCAkX0dbJ3N0eWxlJ11bJ2V4dHN0eWxlJ10gJGV4dHN0eWxlfS0tPgoJCQkJCQk8c3BhbiBjbGFzcz0ic3NsY3RfYnRuIiBvbmNsaWNrPSJleHRzdHlsZSgnJGV4dHN0eWxlWzBdJykiIHRpdGxlPSIkZXh0c3R5bGVbMV0iPjxpIHN0eWxlPSdiYWNrZ3JvdW5kOiRleHRzdHlsZVsyXSc+PC9pPjwvc3Bhbj4KCQkJCQk8IS0tey9sb29wfS0tPgoJCQkJPC9kaXY+CgkJCTwhLS17L2lmfS0tPgoJCQk8IS0te2lmICRfR1sndWlkJ119LS0+CgkJCQk8dWwgaWQ9Im15aXRlbV9tZW51IiBjbGFzcz0icF9wb3AiIHN0eWxlPSJkaXNwbGF5OiBub25lOyI+CgkJCQkJPCEtLXtpZiAkX0dbJ3NldHRpbmcnXVsnZm9ydW1zdGF0dXMnXX0tLT48bGk+PGEgaHJlZj0iaG9tZS5waHA/bW9kPXNwYWNlJmRvPXRocmVhZCZ2aWV3PW1lIj57bGFuZyBteXBvc3R9PC9hPjwvbGk+PCEtLXsvaWZ9LS0+CgkJCQkJPCEtLXtpZiAkX0dbJ3NldHRpbmcnXVsnZmF2b3JpdGVzdGF0dXMnXX0tLT48bGk+PGEgaHJlZj0iaG9tZS5waHA/bW9kPXNwYWNlJmRvPWZhdm9yaXRlJnZpZXc9bWUiPntsYW5nIGZhdm9yaXRlfTwvYT48L2xpPjwhLS17L2lmfS0tPgoJCQkJCTwhLS17aWYgJF9HWydzZXR0aW5nJ11bJ2ZyaWVuZHN0YXR1cyddfS0tPjxsaT48YSBocmVmPSJob21lLnBocD9tb2Q9c3BhY2UmZG89ZnJpZW5kIj57bGFuZyBmcmllbmRzfTwvYT48L2xpPjwhLS17L2lmfS0tPgoJCQkJCTwhLS17aG9vay9nbG9iYWxfbXlpdGVtX2V4dHJhfS0tPgoJCQkJPC91bD4KCQkJPCEtLXsvaWZ9LS0+CgkJCTwhLS17c3VidGVtcGxhdGUgY29tbW9uL2hlYWRlcl9xbWVudX0tLT4KCQk8IS0tey9pZn0tLT4KCgkJPCEtLXthZC9oZWFkZXJiYW5uZXIvd3AgYV9ofS0tPgoJCTxkaXYgaWQ9ImhkIj4KCQkJPGRpdiBjbGFzcz0id3AiPgoJCQkJPGRpdiBjbGFzcz0iaGRjIGNsIj4KCQkJCQk8IS0te2V2YWwgJG1uaWQgPSBnZXRjdXJyZW50bmF2KCk7fS0tPgoJCQkJCTxoMj48IS0te2lmICFpc3NldCgkX0dbJ3NldHRpbmcnXVsnbmF2bG9nb3MnXVskbW5pZF0pfS0tPjxhIGhyZWY9IntpZiAkX0dbJ3NldHRpbmcnXVsnZG9tYWluJ11bJ2FwcCddWydkZWZhdWx0J119eyRfR1snc2NoZW1lJ119Oi8veyRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ2RlZmF1bHQnXX0ve2Vsc2V9Li97L2lmfSIgdGl0bGU9IiRfR1snc2V0dGluZyddWydiYm5hbWUnXSI+eyRfR1snc3R5bGUnXVsnYm9hcmRsb2dvJ119PC9hPjwhLS17ZWxzZX0tLT4kX0dbJ3NldHRpbmcnXVsnbmF2bG9nb3MnXVskbW5pZF08IS0tey9pZn0tLT48L2gyPgoJCQkJCTwhLS17dGVtcGxhdGUgY29tbW9uL2hlYWRlcl91c2Vyc3RhdHVzfS0tPgoJCQkJPC9kaXY+CgoJCQkJPGRpdiBpZD0ibnYiPgoJCQkJCTxhIGhyZWY9ImphdmFzY3JpcHQ6OyIgaWQ9InFtZW51IiBvbm1vdXNlb3Zlcj0iZGVsYXlTaG93KHRoaXMsIGZ1bmN0aW9uICgpIHtzaG93TWVudSh7J2N0cmxpZCc6J3FtZW51JywncG9zJzonMzQhJywnY3RybGNsYXNzJzonYScsJ2R1cmF0aW9uJzoyfSk7c2hvd0ZvcnVtbWVudSgkX0dbZmlkXSk7fSkiPntsYW5nIG15X25hdn08L2E+CgkJCQkJPHVsPgoJCQkJCQk8IS0te2xvb3AgJF9HWydzZXR0aW5nJ11bJ25hdnMnXSAkbmF2fS0tPgoJCQkJCQkJPCEtLXtpZiBpc19hcnJheSgkbmF2KSAmJiAkbmF2WydhdmFpbGFibGUnXSAmJiAoISRuYXZbJ2xldmVsJ10gfHwgKCRuYXZbJ2xldmVsJ10gPT0gMSAmJiAkX0dbJ3VpZCddKSB8fCAoJG5hdlsnbGV2ZWwnXSA9PSAyICYmICRfR1snYWRtaW5pZCddID4gMCkgfHwgKCRuYXZbJ2xldmVsJ10gPT0gMyAmJiAkX0dbJ2FkbWluaWQnXSA9PSAxKSl9LS0+PGxpIHtpZiAkbW5pZCA9PSAkbmF2W25hdmlkXSB8fCBzdWJzdHIoJF9TRVJWRVJbJ1JFUVVFU1RfVVJJJ10sIDEpID09IHN0cl9yZXBsYWNlKCcuLycsICcnLCAkbmF2W2ZpbGVuYW1lXSl9Y2xhc3M9ImEiIHsvaWZ9JG5hdltuYXZdPjwvbGk+PCEtLXsvaWZ9LS0+CgkJCQkJCTwhLS17L2xvb3B9LS0+CgkJCQkJPC91bD4KCQkJCQk8IS0te2hvb2svZ2xvYmFsX25hdl9leHRyYX0tLT4KCQkJCTwvZGl2PgoJCQkJPCEtLXtpZiAhZW1wdHkoJF9HWydzZXR0aW5nJ11bJ3BsdWdpbnMnXVsnanNtZW51J10pfS0tPgoJCQkJCTx1bCBjbGFzcz0icF9wb3AgaF9wb3AiIGlkPSJwbHVnaW5fbWVudSIgc3R5bGU9ImRpc3BsYXk6IG5vbmUiPgoJCQkJCTwhLS17bG9vcCAkX0dbJ3NldHRpbmcnXVsncGx1Z2lucyddWydqc21lbnUnXSAkbW9kdWxlfS0tPgoJCQkJCQkgPCEtLXtpZiBpbl9hcnJheSgkbW9kdWxlWydhZG1pbmlkJ10sIGFycmF5KDAsIC0xKSkgfHwgKCRtb2R1bGVbJ2FkbWluaWQnXSAmJiAkX0dbJ2FkbWluaWQnXSA+IDAgJiYgJG1vZHVsZVsnYWRtaW5pZCddID49ICRfR1snYWRtaW5pZCddKX0tLT4KCQkJCQkJIDxsaT4kbW9kdWxlW3VybF08L2xpPgoJCQkJCQkgPCEtLXsvaWZ9LS0+CgkJCQkJPCEtLXsvbG9vcH0tLT4KCQkJCQk8L3VsPgoJCQkJPCEtLXsvaWZ9LS0+CgkJCQkkX0dbc2V0dGluZ11bbWVudW5hdnNdCgkJCQk8ZGl2IGlkPSJtdSIgY2xhc3M9ImNsIj4KCQkJCTwhLS17aWYgJF9HWydzZXR0aW5nJ11bJ3N1Ym5hdnMnXX0tLT4KCQkJCQk8IS0te2xvb3AgJF9HW3NldHRpbmddW3N1Ym5hdnNdICRuYXZpZCAkc3VibmF2fS0tPgoJCQkJCQk8IS0te2lmICRfR1snc2V0dGluZyddWyduYXZzdWJob3ZlciddIHx8ICRtbmlkID09ICRuYXZpZH0tLT4KCQkJCQkJPHVsIGNsYXNzPSJjbCB7aWYgJG1uaWQgPT0gJG5hdmlkfWN1cnJlbnR7L2lmfSIgaWQ9InNuYXZfJG5hdmlkIntpZiAkbW5pZCAhPSAkbmF2aWR9IHN0eWxlPSJkaXNwbGF5Om5vbmUiey9pZn0+CgkJCQkJCSRzdWJuYXYKCQkJCQkJPC91bD4KCQkJCQkJPCEtLXsvaWZ9LS0+CgkJCQkJPCEtLXsvbG9vcH0tLT4KCQkJCTwhLS17L2lmfS0tPgoJCQkJPC9kaXY+CgkJCQk8IS0te2FkL3N1Ym5hdmJhbm5lci9hX211fS0tPgoJCQkJPCEtLXtzdWJ0ZW1wbGF0ZSBjb21tb24vcHVic2VhcmNoZm9ybX0tLT4KCQkJPC9kaXY+CgkJPC9kaXY+CgoJCTwhLS17aG9vay9nbG9iYWxfaGVhZGVyfS0tPgoJPCEtLXsvaWZ9LS0+CgoJPGRpdiBpZD0id3AiIGNsYXNzPSJ3cCI+Cg==
qidao123.com ToB IT社区-企服评测·应用市场»论坛 › 主机系统 › linux › Express静态文件服务器演示与实践
返回列表 发新帖

Express静态文件服务器演示与实践

[复制链接]
发表于 2026-1-17 23:33:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本文另有配套的佳构资源,点击获取  

  简介:Express是一个轻便且机动的Node.js web应用开辟框架,具有强大的路由处置惩罚、中心件体系、静态文件服务、模板引擎支持和错误处置惩罚功能。本项目是一个Express demo,通过实现一个简单的静态文件服务器,演示了怎样举行哀求转发、哀求纪录以及通用设置设置。开辟者可以通太过析这个demo来把握Express框架的底子使用方法,包罗怎样设置和启动一个静态文件服务器,怎样界说和使用中心件来纪录哀求信息,以及怎样通过设置文件设置服务器活动。

1. Express框架简介与项目创建

Express框架简介

  Express是一个简单但功能强大的Node.js Web应用框架,它为开辟者提供了多种轻便的方式来创建各种Web和移动应用。它抽象掉了服务器端底层的细节,让开辟者专注于应用的构建。Express的焦点是机动的路由体系,它支持多种HTTP哀求范例,如GET、POST、PUT、DELETE等,并答应使用中心件来处置惩罚哀求与相应周期中的各种使命。
Express项目创建

  创建一个新的Express项目是开始构建Web应用的第一步。可以通过以下步调完成:

  •    情况准备 :确保你已经安装了Node.js情况,并通过npm(Node.js的包管理器)全局安装了Express天生器,使用下令  npm install -g express-generator  。
  •    项目天生 :在终端中运行  express myapp  (此中  myapp  是你的项目名)来创建一个新的项目。
  •    安装依靠 :进入项目目次后运行  npm install  来安装项目所需的依靠。
  •    启动应用 :使用  npm start  下令启动服务器,Express天生器默认在3000端口监听。
通过这些步调,你将拥有一个底子的Express应用布局,此中包罗了中心件、路由等焦点组件,为后续开辟打下底子。
2. 路由处置惩罚实现

2.1 路由概念与功能

2.1.1 路由界说及作用

  路由是Web应用中一种紧张的概念,它负责界说应用步调的端点(URIs)以及这些端点的相应活动。在Express框架中,一个路由可以被视作一个带有特定HTTP方法的路径模式(path pattern)和一个回调函数(callback function)的组合。回调函数被调用时,可以访问哀求对象(request object),相应对象(response object),以及应用中后续中心件的下一个回调函数(next callback function)。
  一个根本的Express路由布局如下所示:
  1. app.METHOD(PATH, HANDLER);
复制代码
此中,  METHOD  是 HTTP 哀求方法,如 GET、POST、PUT、DELETE;  PATH  是服务器上的路径;  HANDLER  是当路由匹配时实行的函数。
2.1.2 根本路由与动态路由

  根本路由是最简单的路由情势,它匹配特定的路径和HTTP方法。比方:
  1. app.get('/about', function (req, res) {
  2.   res.send('About page');
  3. });
复制代码
动态路由答应我们在路径中包罗变量部门,这些部门可以通过路由的回调函数举行访问。比方:
  1. app.get('/user/:id', function (req, res) {
  2.   res.send('User ' + req.params.id);
  3. });
复制代码
2.2 路由参数与查询

2.2.1 路由参数处置惩罚

  在Express中,路由参数是一种在路由路径中界说变量的便捷方式。这些参数可以通过  req.params  对象来访问。比方,路由界说为  /user/:id  时,可以如许获取参数值:
  1. app.get('/user/:id', function (req, res) {
  2.   res.send('User ' + req.params.id);
  3. });
复制代码
路由参数使用冒号  :  后跟参数名,然后在回调函数中通过  req.params  对象访问。
2.2.2 查询字符串分析

  查询字符串是在URL中以  ?  开始,后跟多个键值对,由  &  符号分隔。在Express中,可以通过  req.query  对象来访问这些查询参数。比方:
  1. app.get('/search', function (req, res) {
  2.   console.log(req.query);
  3.   res.send('Search query: ' + req.query.q);
  4. });
复制代码
如果哀求URL是  /search?q=express  ,  req.query.q  将会输出  'express'  。
2.3 路由中心件应用

2.3.1 中心件在路由中的脚色

  中心件在Express中充当着过滤器的脚色,它们可以访问哀求对象(req)和相应对象(res),然后在下一个中心件或路由处置惩罚器实行前实行任何代码。中心件可以实行如下使命:


  • 实行任何代码
  • 修改哀求和相应对象
  • 闭幕哀求-相应循环
  • 调用下一个中心件函数
中心件函数通常具有以下情势:
  1. function(req, res, next) {
  2.   // 执行一些代码
  3.   // 如果当前中间件不终结请求-响应循环,则调用 next() 来调用下一个中间件
  4.   next();
  5. }
复制代码
2.3.2 路由级别中心件实践

  路由级别的中心件特定于一个或几个路由,而不是全局中心件那样应用于全部路由。它们在界说路由的时间直接使用:
  1. app.get('/user/:id', function (req, res, next) {
  2.   // 中间件逻辑
  3.   next();
  4. }, function (req, res) {
  5.   res.send('User ' + req.params.id);
  6. });
复制代码
在上面的例子中,第一个函数是中心件逻辑,它在第二个函数(路由处置惩罚器)之前实行。如果中心件逻辑必要停止哀求-相应循环,则不必要调用  next()  。
3. 中心件体系实现

  中心件是构成 Express 应用的紧张构成部门,它是一种通过哀求-相应循环来访问应用哀求对象 (req)、相应对象 (res) 以及应用的哀求-相应循环流程中的下一个中心件函数的函数。在这一章节中,我们将详细先容中心件的理论底子、分类以及使用方法,末了还将探究怎样实现一个强大的错误处置惩罚中心件。
3.1 中心件底子理论

3.1.1 中心件的界说与用途

  中心件在 Express 应用中饰演着极其紧张的脚色。它的焦点概念是一个函数,这个函数可以访问哀求对象  req  、相应对象  res  以及应用步调中处于哀求-相应循环流程中的下一个中心件函数。中心件通常被用来实行以下使命:


  • 实行任何代码。
  • 修改哀求和相应对象。
  • 闭幕哀求-相应循环。
  • 调用堆栈中的下一个中心件。
3.1.2 中心件的实行流程

  一个 Express 应用可以使用一系列的中心件函数。当应用收到一个 HTTP 哀求时,它开始实行数组中的中心件函数,直到到达“止境”大概“出口”(通常是一条发送相应的语句)。在某些情况下,中心件函数也可以跳过后续中心件或路由的实行。
  通常,中心件函数可以实行以下使命:


  • 实行代码。
  • 修改哀求和相应对象。
  • 竣事哀求-相应循环。
  • 调用堆栈中的下一个中心件。
在下面的伪代码示例中,  next  是一个中心件函数,它调用堆栈中的下一个中心件函数:
  1. function myMiddleware(request, response, next) {
  2.   // 执行一些代码...
  3.   next(); // 调用堆栈中的下一个中间件
  4. }
复制代码
3.2 中心件的范例与使用

3.2.1 应用级中心件

  应用级中心件是绑定到  app  对象的中心件函数。它可以直接绑定到应用对象上,也可以使用  app.use()  或  app.METHOD()  方法绑定。
  比方,以下代码展示了如作甚应用界说一个简单的中心件函数:
  1. app.use(function (req, res, next) {
  2.   console.log('这是一个中间件函数');
  3.   next();
  4. });
复制代码
3.2.2 路由级中心件

  路由级中心件和应用级中心件的工作方式险些完全一样,只是它们是绑定到  express.Router()  上。下面的示例中创建了一个路由对象,并为其添加了一个中心件函数和一个路由处置惩罚步调:
  1. var router = express.Router();
  2. router.use(function (req, res, next) {
  3.   console.log('这是路由级中间件');
  4.   next();
  5. });
  6. router.get('/', function (req, res) {
  7.   res.send('Hello World');
  8. });
  9. app.use('/myRouter', router);
复制代码
3.3 错误处置惩罚中心件

  错误处置惩罚中心件是一个特别的中心件函数,它必须带有四个参数:  err  ,  req  ,  res  , 和  next  。纵然你不必要使用  req  和  res  对象,也必须在署名中声明它们,以便错误处置惩罚中心件能被精确辨认。
3.3.1 自界说错误处置惩罚

  在 Express 中,可以通过使用四个参数来界说错误处置惩罚中心件,而不是三个参数。纵然不必要使用  next  对象,也必须在署名中包罗它,否则中心件会被看成通例中心件处置惩罚。
  1. app.use(function(err, req, res, next) {
  2.   console.error(err.stack);
  3.   res.status(500).send('发生错误!');
  4. });
复制代码
3.3.2 全局错误捕捉

  Express 应用可以在任何位置界说多个错误处置惩罚中心件。为了最佳实践,应该把错误处置惩罚中心件放在全部中心件和路由之后,以确保一旦在应用中发生错误,它就可以被错误处置惩罚中心件捕捉。
  1. app.get('/', function (req, res) {  throw new Error('发生错误!');});// 末了界说的中心件是全局错误处置惩罚器app.use(function(err, req, res, next) {
  2.   console.error(err.stack);
  3.   res.status(500).send('发生错误!');
  4. });
复制代码
以上内容为第三章的详细先容,涵盖中心件的底子理论、范例以及错误处置惩罚。在接下来的内容中,我们将继承探究如作甚 Express 应用提供静态文件服务、模板引擎的支持,以及怎样举行哀求纪录和通用设置设置。
4. 静态文件服务实现

  在Web开辟中,静态文件服务是构建应用不可或缺的一部门。它涉及到向客户端提供图片、样式表、JavaScript文件等资源。本章节将详细先容静态文件服务的原理、设置方法、优化计谋以及安全性步调。
4.1 静态文件服务原理

4.1.1 文件服务与资源定位

  静态文件服务的焦点概念是将存储在服务器上的文件直接发送给哀求它的客户端。比方,当你访问一个网页时,欣赏器会哀求网页所引用的CSS、JavaScript文件等。服务器吸取到哀求后,查找相应文件并将其内容发送回客户端。
  在Express框架中,静态文件服务通常通过内置的  express.static  中心件实现。该中心件提供了一种便捷的方法来设置静态资源目次。比方:
  1. const express = require('express');
  2. const app = express();
  3. const path = require('path');
  4. // 设置静态文件目录
  5. app.use(express.static(path.join(__dirname, 'public')));
复制代码
在上述代码中,  express.static  中心件被用来设置名为  public  的目次作为静态资源目次。当哀求一个静态文件时,Express会主动查找该目次下的对应文件,并将文件内容发送给客户端。
4.1.2 服务服从优化计谋

  固然静态文件服务在Express中非常简单,但在生产情况中,服务静态文件时思量性能优化计谋好坏常紧张的。下面是一些常见的优化步调:


  • 使用CDN :内容分发网络(CDN)可以缓存静态资源,并将它们分布到天下各地的服务器上,以便用户可以大概从隔断他们迩来的服务器获取资源,从而淘汰耽误。
  • 文件压缩 :使用Gzip压缩可以淘汰传输文件的巨细,加快加载时间。在Express中,可以使用  compression  中心件来实现。
  • 缓存控制 :在相应头中设置  Cache-Control  可以让欣赏器知道怎样缓存文件,淘汰不须要的服务器哀求。
  • 版本控制 :给静态资源文件添加版本号可以制止缓存题目。可以通过在文件名中添加时间戳或MD5哈希值来实现。
4.2 静态文件的设置与访问

4.2.1 设置静态资源路径

  为了更好地构造项目布局,我们通常会将静态资源放在项目中的差别目次下。好比,将图片放在  public/img  目次下,CSS文件放在  public/css  目次劣等。
  我们可以在  express.static  中心件中指定多个目次:
  1. app.use(express.static(path.join(__dirname, 'public')));
  2. app.use(express.static(path.join(__dirname, 'uploads')));
复制代码
如许设置后,Express会按照中心件序次搜刮静态文件。也就是说,当哀求一个文件时,Express起首会在  public  目次下搜刮,如果未找到,则会在  uploads  目次下搜刮。
4.2.2 静态资源访问权限控制

  在某些情况下,我们大概必要控制对静态资源的访问权限,好比限定只有认证用户才气下载特定的文件。这可以通过中心件来实现:
  1. const authenticate = (req, res, next) => {
  2.     if (req.isAuthenticated()) {
  3.         next();
  4.     } else {
  5.         res.status(403).send('Access Denied');
  6.     }
  7. };
  8. app.get('/download/:filename', authenticate, (req, res) => {
  9.     res.sendFile(path.join(__dirname, 'uploads', req.params.filename));
  10. });
复制代码
在这个例子中,我们创建了一个名为  authenticate  的中心件来查抄用户是否已经认证。只有通过认证的用户才气访问  /download/:filename  路由来下载文件。
4.3 静态文件服务的安全性

4.3.1 安全访问控制

  除了通过身份验证来控制访问外,还可以通过其他一些安全步调来掩护静态文件:


  • 限定目次欣赏 :默认情况下,一些Web服务器答应用户欣赏目次内容。我们可以通过Express来关闭这一功能,防止用户看到不应袒露的文件列表。
  • 文件范例查抄 :只答应特定范例的文件被访问,可以防止恶意文件上传和实行。
4.3.2 防止目次遍历攻击

  目次遍历攻击是指攻击者试图通过在哀求的文件路径中使用  ../  来访问服务器上非公开的目次和文件。为了防止此类攻击,我们可以在路径处置惩罚逻辑中参加验证,确保哀求的路径不会跳出预定的目次:
  1. const allowlist = [ 'images', 'css', 'js', 'uploads' ];
  2. app.use('/static', (req, res, next) => {
  3.     const segments = req.path.split('/').filter(Boolean);
  4.     if (!segments.every(segment => allowlist.includes(segment))) {
  5.         return res.status(403).send('Access Denied');
  6.     }
  7.     express.static(path.join(__dirname, 'public'))(req, res, next);
  8. });
复制代码
通过以上代码,我们创建了一个名为  /static  的路由,只有  allowlist  中指定的目次下的哀求才被答应访问。其他任何试图访问其他目次的利用都会被拒绝,从而进步了安全性。
  通过本章节的先容,我们相识了静态文件服务的原理,设置方法,优化计谋以及安全性步调。下一章节将继承探究Express中的模板引擎支持。
5. 模板引擎支持

5.1 模板引擎概述

5.1.1 模板引擎的作用

  在Web开辟中,模板引擎提供了一种将数据与HTML布局分离的方式,使得开辟者可以大概将网站的展示逻辑与业务逻辑清晰地分开。模板引擎通过预界说的语法,将数据绑定到视图模板中,终极天生HTML页面返回给客户端。这种分离的利益是多方面的:


  • 代码可维护性 :前端筹划师可以独立于后端开辟职员修改页面布局,无需深入明确后端逻辑。
  • 安全性 :通过模板引擎可以制止直接在模板中嵌入恶意代码,由于模板引擎通常会提供安全的输出机制。
  • 复用性 :模板可以被多个差别的路由或控制器复用,确保了同等性和淘汰重复代码。
  • 动态内容展示 :动态地将数据如用户信息、商品列表等插入到HTML中,使得页面内容可以根据数据的差别而变革。
5.1.2 常见模板引擎先容

  在Node.js社区,有很多良好的模板引擎可以与Express框架搭配使用。一些盛行的模板引擎包罗:


  • EJS :一种简单的模板语言,答应你在HTML标签中嵌入Ruby-like的语法。
  • Pug (前身为Jade):一种高度抽象的模板语言,它使用缩进和换行来代替闭合标签。
  • Handlebars :与jQuery的同名前端库差别,它提供了更为强大的条件和循环控制功能。
  • Nunjucks :由Mozilla开辟,它是一个功能丰富的模板库,支持继承和宏。
每种模板引擎都有本身的语法和最佳实践。选择哪一种模板引擎紧张取决于个人偏好和项目需求。
5.2 模板引擎设置与使用

5.2.1 Express整合模板引擎

  要将模板引擎与Express框架整合使用,起首必要安装对应的npm包。以EJS为例,通过以下下令安装:
  1. npm install ejs
复制代码
安装完成后,将EJS设置为Express应用的默认视图引擎:
  1. const express = require('express');
  2. const app = express();
  3. app.set('view engine', 'ejs');
复制代码
以上代码将告诉Express框架使用EJS作为默认的模板引擎。之后,你可以直接使用  res.render  方法来渲染模板文件:
  1. app.get('/', (req, res) => {
  2.   res.render('index', { title: 'Express', message: 'Hello World!' });
  3. });
复制代码
在上述示例中,  index  是位于视图目次(默以为  views  目次)中的EJS模板文件,而  title  和  message  是转达给模板的数据对象。
5.2.2 模板数据转达与渲染

  当调用  res.render  方法时,Express会主动查找  views  目次下对应的模板文件,并将转达的数据作为参数渲染模板。模板文件中的数据表达通常使用模板引擎的特定语法。比方,在EJS模板文件  index.ejs  中,你可以如许使用转达的数据:
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.   <title><%= title %></title>
  5. </head>
  6. <body>
  7.   <h1><%= message %></h1>
  8. </body>
  9. </html>
复制代码
在这个例子中,  <%= title %>  和  <%= message %>  是EJS的输出标志,它们会被渲染时传入的数据值更换。在渲染的过程中,模板引擎会分析这些标志并插入相应的数据。
5.3 模板引擎高级特性

5.3.1 继承与区块

  模板继承是一种强大的特性,它答应你创建一个根本的页面布局(通常称为“布局”),然后在差别的模板中复用这个布局。在EJS中,可以使用  <%- include %>  标志来包罗其他模板,大概使用区块(block)来自界说布局的部门内容。比方,创建一个底子布局  layout.ejs  :
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.   <title><%= title %></title>
  5. </head>
  6. <body>
  7.   <%- body %>
  8. </body>
  9. </html>
复制代码
然后,在其他模板文件中,你可以使用  <%- include('layout') %>  来包罗布局,同时使用  <% block body %><% end %>  界说自界说的内容区块:
  1. <%- include('layout') %>
  2. <% block body %>
  3.   <h1>Welcome to the home page</h1>
  4. <% end %>
复制代码
5.3.2 条件与循环控制

  模板引擎还提供条件判定和循环控制的语法,答应开辟者在模板中举行逻辑判定和迭代利用。在EJS中,条件判定和循环控制使用如下语法:
  1. <% if (user) { %>
  2.   <h2><%= user.name %></h2>
  3. <% } %>
  4. <ul>
  5.   <% for (let i = 0; i < users.length; i++) { %>
  6.     <li><%= users[i].name %></li>
  7.   <% } %>
  8. </ul>
复制代码
上述代码中,  <% if %>  和  <% for %>  是EJS中的控制语句,它们答应开辟者在模板中编写JavaScript代码来控制输出。
  通过使用模板引擎的高级特性,开辟者可以创建更加动态和可维护的Web应用。同时,模板引擎的机动性和扩展性也为项目提供了更多的大概性。
6. 错误处置惩罚与哀求转发

6.1 错误处置惩罚机制

6.1.1 自界说错误处置惩罚流程

  在Web应用步调中,错误处置惩罚是至关紧张的部门。它不但保障了用户体验,而且对应用步调的稳固性和安全性起到了关键作用。自界说错误处置惩罚流程是进步错误相应本领和用户体验的有效本领。
  在Express框架中,错误处置惩罚通常通过中心件完成。错误处置惩罚中心件是一个特别的中心件,它可以大概捕捉在其前面全部中心件中抛出的错误。其根本的实现方法如下:
  1. app.use((err, req, res, next) => {
  2.   console.error(err.stack);
  3.   res.status(500).send('Something broke!');
  4. });
复制代码
这个中心件会捕捉全部前置中心件中未被处置惩罚的错误,并举行相应处置惩罚。  err  参数代表错误对象,  req  和  res  分别是哀求和相应对象,  next  是将控制权转达给下一个中心件的函数。
  一个完备的错误处置惩罚流程通常包罗以下几个步调:

  • 错误捕捉 :在哀求处置惩罚流程中捕捉到错误,无论是同步代码抛出的错误照旧异步利用中的错误。
  • 错误纪录 :纪录错误信息,便于题目的追踪和分析,可纪录到文件、数据库或日记服务。
  • 错误反馈 :向客户端反馈错误信息,通常以JSON格式或HTML页面出现。
  • 规复 :在某些情况下,错误处置惩罚后可以大概将应用步调状态规复到安全状态,继承吸取新的哀求。
实现一个错误处置惩罚中心件,不但可以大概提拔用户面对错误时的体验,还可以大概资助开辟者快速定位题目。
6.1.2 错误中心件最佳实践

  最佳实践应包罗以下几个方面:


  • 会合处置惩罚 :将错误处置惩罚逻辑会合到一个或少数几个中心件中,方便管理和复用。
  • 同一错误格式 :确保全部的错误相应都接纳同一的格式,好比在JSON相应中使用  { "error": "详细错误信息" }  。
  • 详细错误信息 :在开辟和测试情况中提供详细的错误信息,但在生产情况中应制止泄漏敏感信息。
  • 错误级别区分 :根据错误的严峻程度,决定是否必要纪录到日记、怎样相应给客户端,以及是否必要关照开辟者。
  • 异步错误处置惩罚 :对于异步利用中产生的错误,确保精确地使用Promise的  .catch()  方法,大概在异步函数中使用  try...catch  布局。
错误处置惩罚是一个涉及步调筹划哲学的题目。良好的错误处置惩罚机制可以大概提拔应用的结实性,而错误处置惩罚的最佳实践可以大概包管应用的可维护性和用户体验。
6.2 哀求转发机制

6.2.1 基于路由的哀求转发

  哀求转发指的是将客户端的哀求转发到另一个服务器或应用步调的资源。在Express中,哀求转发可以通过中心件实现,而且可以是内部或外部资源之间的转发。
  在Express中,  res.redirect()  方法常被用来举行内部哀求转发。比方,以下代码展示了怎样使用路由处置惩罚步调将哀求重定向到另一个路由:
  1. // 假设我们有一个API路径为 /api/v1/items 的GET请求
  2. app.get('/api/v1/items', function(req, res) {
  3.   // 某些情况下,我们可能需要将请求转发到另一个路径
  4.   // 比如,在API版本更新时,旧版本路径被废弃,需要重定向到新版本
  5.   res.redirect('/api/v2/items');
  6. });
  7. // 新版本的API路由处理程序
  8. app.get('/api/v2/items', function(req, res) {
  9.   // API逻辑处理
  10. });
复制代码
除了内部重定向外,Express也可以转发哀求到外部服务器。这通常涉及到创建一个新的HTTP哀求,并将原始哀求的某些信息(好比headers、cookies等)转达给外部服务。比方,使用第三方API大概服务端署理时:
  1. app.get('/external-api', (req, res) => {
  2.   const options = {
  3.     url: '***',
  4.     headers: {
  5.       'X-Custom-Header': req.get('X-Custom-Header')
  6.     }
  7.   };
  8.   // 使用第三方库(如request-promise)来转发请求
  9.   request(options)
  10.     .then(response => res.send(response))
  11.     .catch(error => res.status(500).send(error.message));
  12. });
复制代码
6.2.2 哀求转发的性能思量

  在实行哀求转发时,必须思量到性能影响。错误的转发设置大概导致哀求链路中的性能瓶颈,以致导致服务瓦解。下面罗列了几个关键的性能思量因素:


  • 重定向链路 :制止创建重定向链路,比方在重定向后又举行新的重定向。这会无谓增长哀求的耽误,而且斲丧更多服务器资源。
  • 缓存机制 :在转发哀求时,可以使用缓存技能淘汰对原始数据源的哀求次数,进步相应速率。
  • 负载均衡 :当转发哀求到内部或外部服务时,公道使用负载均衡可以分散哀求压力,进步团体体系的稳固性和可用性。
  • 并发限定 :对并发哀求举行限定,制止服务在高并发情况下被哀求压垮。
  • 限流计谋 :对哀求频率举行限定,比方限定每分钟的哀求次数,可以有效防止突发流量导致的服务器故障。
精确地使用哀求转发可以使开辟更加机动,但必要确保转发机制不会对应用步调的性能产生负面影响。
7. 哀求纪录与通用设置设置

  在构建和维护Web应用时,哀求纪录与通用设置设置是确保应用稳固性和可维护性的关键构成部门。本章节将深入探究怎样实现有效的哀求纪录以及怎样设置通用设置以顺应差别的开辟和摆设情况。
7.1 哀求纪录的实现

  哀求纪录,又称日记纪录,是纪录服务器吸取、处置惩罚和相应客户端哀求的过程。有效的日记纪录可以资助开辟者监控监控应用状态,追踪错误,以及举行安全审计。
7.1.1 日记纪录级别与方式

  日记纪录级别包罗但不限于:错误(Error)、告诫(Warning)、信息(Info)、调试(Debug)。在Express中,可以通过使用第三方中心件如  morgan  来简化日记纪录的实现。以下是一个使用  morgan  中心件的例子:
  1. const express = require('express');
  2. const morgan = require('morgan');
  3. const app = express();
  4. // 以tiny格式记录日志日志,这种方式较为简洁
  5. app.use(morgan('tiny'));
复制代码
别的,日记纪录方式还可以包罗输出到控制台、文件、数据库或发送到日记管理体系。每种方式都有其上风和实用场景。比方,将日记写入文件便于审计,而发送到日记管理体系则有助于会合监控监控和分析。
7.1.2 日记的存储与查询

  日记文件会不绝增长,因此必要符合的存储计谋以制止耗尽磁盘空间。常见的做法是定期轮转(log rotation),如许旧的日记文件会被主动压缩并归档。Express原生不提供日记轮转功能,但可以使用如  winston  或  log4js  等库来实现。
  查询日记时,可以使用简单的文本搜刮工具,也可以使用专业的日记分析工具,如ELK(Elasticsearch, Logstash, Kibana)堆栈。这将答应你根据差别的维度对日记举行过滤、聚合和可视化。
7.2 通用设置设置方法

  应用步调的通用设置包罗应用名称、情况变量、服务端口等,而这些设置的设置方式会影相应用的机动性和可维护性。
7.2.1 应用设置与情况设置

  区分开辟、测试和生产情况的设置是最佳实践之一。比方,开辟情况中大概必要详细的日记输出和调试信息,而生产情况则必要优化性能并潜伏敏感信息。
  在Node.js应用中,可以通过情况变量或设置文件来管理差别情况的设置。以下是一个使用情况变量的示例:
  1. const port = process.env.PORT || 3000;
  2. const app = express();
  3. app.listen(port, () => {
  4.   console.log(`Server is running on port ${port}`);
  5. });
复制代码
通过设置情况变量  PORT  ,可以轻松地在差别的服务器设置中切换监听端口。
7.2.2 中心件与路由的设置管理

  中心件和路由的设置管理必要思量到组件的重用和设置的会合化。这可以通过模块化中心件和路由文件来实现,然后在主应用文件中引入和使用它们。比方:
  1. // middleware/logger.js
  2. module.exports = (req, res, next) => {
  3.   console.log(`${req.method} request for ${req.url}`);
  4.   next();
  5. };
  6. // routes/index.js
  7. const express = require('express');
  8. const router = express.Router();
  9. router.use(logger); // 使用上面定义的日志日志中间件
  10. router.get('/', (req, res) => {
  11.   res.send('Home page');
  12. });
  13. module.exports = router;
  14. // app.js
  15. const routes = require('./routes/index');
  16. app.use('/', routes);
复制代码
在上述例子中,我们创建了一个日记中心件  logger  并在路由文件中使用它。然后在主应用文件  app.js  中引入并应用该路由。
7.3 Express项目布局和紧张文件分析

  末了,一个清晰的项目布局和构造良好的代码是保持项目长期可连续发展的关键。接下来,让我们探究一个典范的Express项目布局,并对紧张文件举行分析。
7.3.1 项目文件构造布局

  一个典范的Express项目布局如下所示:
  1. my-express-app/
  2. |-- node_modules/
  3. |-- public/
  4. |-- views/
  5. |-- app.js
  6. |-- package.json
  7. |-- config/
  8.     |-- config.env
复制代码


  •   node_modules/  :包罗全部项目依靠。
  •   public/  :存放静态资源如CSS、JavaScript和图片。
  •   views/  :存放视图模板文件。
  •   app.js  :主应用文件。
  •   package.json  :项目依靠和脚本分析。
  •   config/  :存放差别情况的设置文件。
7.3.2 焦点文件功能分析



  •   app.js  :启动服务器,加载中心件和路由文件。
  •   package.json  :界说项目元数据,如版本、形貌、入口文件和依靠等。
  • 设置文件(  config.env  ):根据当前情况加载差别的设置变量。
  1. // config.env 示例
  2. PORT=3000
  3. NODE_ENV=development
复制代码
这种布局和设置方式可以让项目更易于管理和扩展,便于团队协作,而且容易维护。
  通过这些章节的讨论,我们已经相识了哀求纪录的紧张性和实现方法,以及怎样设置通用设置来顺应差别的摆设情况。上述的代码示例和项目布局分析为构建和维护高效、可扩展的Express应用提供了结实的底子。
   本文另有配套的佳构资源,点击获取  

  简介:Express是一个轻便且机动的Node.js web应用开辟框架,具有强大的路由处置惩罚、中心件体系、静态文件服务、模板引擎支持和错误处置惩罚功能。本项目是一个Express demo,通过实现一个简单的静态文件服务器,演示了怎样举行哀求转发、哀求纪录以及通用设置设置。开辟者可以通太过析这个demo来把握Express框架的底子使用方法,包罗怎样设置和启动一个静态文件服务器,怎样界说和使用中心件来纪录哀求信息,以及怎样通过设置文件设置服务器活动。
  本文另有配套的佳构资源,点击获取  

回复

使用道具 举报

返回列表 发新帖
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录

QQ|手机版|qidao123.com IT社区;IT企服评测▪应用市场 ( 浙ICP备20004199|浙ICP备20004199号 )|网站地图

GMT+8, 2026-11-11 09:14 , Processed in 0.025247 second(s), 7 queries , Redis On.

Powered by Discuz! X3.5 Licensed

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表