! Copyright (C) 2004, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: calendar io io.files kernel math math.order math.parser namespaces parser sequences strings assocs hashtables debugger mime.types sorting logging calendar.format accessors splitting io.encodings.binary fry xml.entities destructors urls html.elements html.templates.fhtml http http.server http.server.responses http.server.redirection ; IN: http.server.static TUPLE: file-responder root hook special allow-listings ; : modified-since ( request -- date ) "if-modified-since" header ";" split1 drop dup [ rfc822>timestamp ] when ; : modified-since? ( filename -- ? ) request get modified-since dup [ [ file-info modified>> ] dip after? ] [ 2drop t ] if ; : ( root hook -- responder ) file-responder new swap >>hook swap >>root H{ } clone >>special ; : (serve-static) ( path mime-type -- response ) [ [ binary &dispose ] dip binary >>content-charset ] [ drop file-info [ size>> ] [ modified>> ] bi ] 2bi [ "content-length" set-header ] [ "last-modified" set-header ] bi* ; : ( root -- responder ) [ (serve-static) ] ; : serve-static ( filename mime-type -- response ) over modified-since? [ file-responder get hook>> call ] [ 2drop <304> ] if ; : serving-path ( filename -- filename ) file-responder get root>> trim-right-separators "/" rot "" or trim-left-separators 3append ; : serve-file ( filename -- response ) dup mime-type dup file-responder get special>> at [ call ] [ serve-static ] ?if ; \ serve-file NOTICE add-input-logging : file. ( name -- ) dup link-info directory? [ "/" append ] when dup escape-string write ; : directory. ( path -- ) dup file-name [ ] [ [

file-name escape-string write

] [
    directory-files [
  • file.
  • ] each
] bi ] simple-page ; : list-directory ( directory -- response ) file-responder get allow-listings>> [ '[ _ directory. ] "text/html" ] [ drop <403> ] if ; : find-index ( filename -- path ) "index.html" append-path dup exists? [ drop f ] unless ; : serve-directory ( filename -- response ) url get path>> "/" tail? [ dup find-index [ serve-file ] [ list-directory ] ?if ] [ drop url get clone [ "/" append ] change-path ] if ; : serve-object ( filename -- response ) serving-path dup exists? [ dup file-info directory? [ serve-directory ] [ serve-file ] if ] [ drop <404> ] if ; M: file-responder call-responder* ( path responder -- response ) file-responder set ".." over member? [ drop <400> ] [ "/" join serve-object ] if ; ! file responder integration : enable-fhtml ( responder -- responder ) [ "text/html" ] "application/x-factor-server-page" pick special>> set-at ;