! 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 ;