@@ -2976,8 +2976,8 @@ inline std::string from_i_to_hex(size_t n) {
29762976inline std::string compute_etag (const FileStat &fs) {
29772977 if (!fs.is_file ()) { return std::string (); }
29782978
2979- size_t mtime = fs.mtime ();
2980- size_t size = fs.size ();
2979+ auto mtime = static_cast < size_t >( fs.mtime () );
2980+ auto size = fs.size ();
29812981
29822982 return std::string (" W/\" " ) + from_i_to_hex (mtime) + " -" +
29832983 from_i_to_hex (size) + " \" " ;
@@ -3161,8 +3161,8 @@ inline bool FileStat::is_dir() const {
31613161 return ret_ >= 0 && S_ISDIR (st_.st_mode );
31623162}
31633163
3164- inline size_t FileStat::mtime () const {
3165- return ret_ >= 0 ? static_cast <size_t >(st_.st_mtime ) : 0 ;
3164+ inline time_t FileStat::mtime () const {
3165+ return ret_ >= 0 ? static_cast <time_t >(st_.st_mtime ) : 0 ;
31663166}
31673167
31683168inline size_t FileStat::size () const {
@@ -8373,6 +8373,12 @@ inline bool Server::handle_file_request(Request &req, Response &res) {
83738373 if (!etag.empty ()) {
83748374 auto inm = req.get_header_value (" If-None-Match" );
83758375 bool matched = false ;
8376+ // NOTE: We use exact string matching here. This works correctly
8377+ // because our server always generates weak ETags (W/"..."), and
8378+ // clients typically send back the same ETag they received.
8379+ // RFC 9110 Section 8.8.3.2 allows weak comparison for
8380+ // If-None-Match, where W/"x" and "x" would match, but this
8381+ // simplified implementation requires exact matches.
83768382 detail::split (inm.data (), inm.data () + inm.size (), ' ,' ,
83778383 [&](const char *b, const char *e) {
83788384 if (!matched) {
0 commit comments