size context weighting
This commit is contained in:
parent
06c5b26b5f
commit
5f3ed30ba4
40
langsmoke
40
langsmoke
|
@ -16,22 +16,34 @@ size=$(du -sm $1 | cut -f1)
|
||||||
let "size++"
|
let "size++"
|
||||||
|
|
||||||
src=$1
|
src=$1
|
||||||
bz3=$(bzip3 -vf $1 /dev/null 2>&1 | grep -oE "[0-9]+ bytes" | grep -oE "[0-9]+")
|
bz3=$(bzip3 -fc $1 | wc -c)
|
||||||
|
lz4=$(lz4 -1c $1 2>/dev/null | wc -c)
|
||||||
|
|
||||||
|
max=$(du ref_* | sort -nr | head -n 1 | cut -f-1)
|
||||||
|
min=$(du ref_* | sort -n | head -n 1 | cut -f-1)
|
||||||
|
abs=$(python3 -c "print(abs($max-$min))")
|
||||||
|
|
||||||
function do_stat {
|
function do_stat {
|
||||||
# 20MB cutoff.
|
# 20MB cutoff.
|
||||||
l_stat=$(cat ref_$1 $src | head -c 20000000 | bzip3 -eb $size | wc -c)
|
ss=$(du ref_$1 | cut -f-1)
|
||||||
l_ref=$2
|
|
||||||
sim=$(python3 -c "print(100*(1-($l_stat - min($l_ref, $bz3)) / (max($l_ref, $bz3))))")
|
bz_stat=$(cat ref_$1 $src | head -c 20000000 | bzip3 -eb $size | wc -c)
|
||||||
echo $sim
|
bz_ref=$(cat ref_$1 | bzip3 -eb $size | wc -c)
|
||||||
|
bz_sim=$(python3 -c "print(100*($ss/$abs)*(1-($bz_stat - min($bz_ref, $bz3)) / (max($bz_ref, $bz3))))")
|
||||||
|
|
||||||
|
lz_stat=$(cat ref_$1 $src | head -c 20000000 | lz4 -1c | wc -c)
|
||||||
|
lz_ref=$(cat ref_$1 | lz4 -1c | wc -c)
|
||||||
|
lz_sim=$(python3 -c "print(1000*($ss/$abs)*(1-($lz_stat - min($lz_ref, $lz4)) / (max($lz_ref, $lz4))))")
|
||||||
|
|
||||||
|
echo "BZ3: $bz_sim, LZ4: $lz_sim"
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "C: $(do_stat c 38533)"
|
echo "C: $(do_stat c)"
|
||||||
echo "C++: $(do_stat cpp 33606)"
|
echo "C++: $(do_stat cpp)"
|
||||||
echo "Java: $(do_stat java 61196)"
|
echo "Java: $(do_stat java)"
|
||||||
echo "6502: $(do_stat 6502 9039)"
|
echo "6502: $(do_stat 6502)"
|
||||||
echo "Z80: $(do_stat z80 20182)"
|
echo "Z80: $(do_stat z80)"
|
||||||
echo "APL: $(do_stat apl 29173)"
|
echo "APL: $(do_stat apl)"
|
||||||
echo "x86: $(do_stat x86 25753)"
|
echo "x86: $(do_stat x86)"
|
||||||
echo "x64: $(do_stat x64 17809)"
|
echo "x64: $(do_stat x64)"
|
||||||
echo "Shell: $(do_stat sh 44144)"
|
echo "Shell: $(do_stat sh)"
|
403
ref_apl
403
ref_apl
|
@ -439,138 +439,6 @@ lam←{
|
||||||
⍝ See https://dyalog.github.io/Jarvis for documentation
|
⍝ See https://dyalog.github.io/Jarvis for documentation
|
||||||
|
|
||||||
(⎕ML ⎕IO)←1 1
|
(⎕ML ⎕IO)←1 1
|
||||||
|
|
||||||
∇ r←Version
|
|
||||||
:Access public shared
|
|
||||||
r←'Jarvis' '1.14.5' '2023-10-14'
|
|
||||||
∇
|
|
||||||
|
|
||||||
∇ Documentation
|
|
||||||
:Access public shared
|
|
||||||
⎕←'See https://dyalog.github.io/Jarvis'
|
|
||||||
∇
|
|
||||||
|
|
||||||
⍝ User hooks settings
|
|
||||||
:Field Public AppCloseFn←'' ⍝ name of the function to run on application (server) shutdown
|
|
||||||
:Field Public AppInitFn←'' ⍝ name of the application "bootstrap" function
|
|
||||||
:Field Public AuthenticateFn←'' ⍝ name of function to perform authentication,if empty, no authentication is necessary
|
|
||||||
:Field Public SessionInitFn←'' ⍝ Function name to call when initializing a session
|
|
||||||
:Field Public ValidateRequestFn←'' ⍝ name of the request validation function
|
|
||||||
|
|
||||||
⍝ Operational settings
|
|
||||||
:Field Public CodeLocation←'#' ⍝ reference to application code location, if the user specifies a folder or file, that value is saved in CodeSource
|
|
||||||
:Field Public ConnectionTimeout←30 ⍝ HTTP/1.1 connection timeout in seconds
|
|
||||||
:Field Public Debug←0 ⍝ 0 = all errors are trapped, 1 = stop on an error, 2 = stop on intentional error before processing request, 4 = Jarvis framework debugging
|
|
||||||
:Field Public DefaultContentType←'application/json; charset=utf-8'
|
|
||||||
:Field Public ErrorInfoLevel←1 ⍝ level of information to provide if an APL error occurs, 0=none, 1=⎕EM, 2=⎕SI
|
|
||||||
:Field Public Hostname←'' ⍝ external-facing host name
|
|
||||||
:Field Public HTTPAuthentication←'basic' ⍝ valid settings are currently 'basic' or ''
|
|
||||||
:Field Public JarvisConfig←'' ⍝ configuration file path (if any). This parameter was formerly named ConfigFile
|
|
||||||
:Field Public LoadableFiles←'*.apl?,*.dyalog' ⍝ file patterns that can be loaded if loading from folder
|
|
||||||
:Field Public Logging←1 ⍝ turn logging on/off
|
|
||||||
:Field Public Paradigm←'JSON' ⍝ either 'JSON' or 'REST'
|
|
||||||
:Field Public Report404InHTML←1 ⍝ Report HTTP 404 status (not found) in HTML (only valid if HTML interface is enabled)
|
|
||||||
:Field Public UseZip←0 ⍝ Use compression if client allows it, 0- don't compress, 0<- compress if UseZip≤≢payload
|
|
||||||
:Field Public ZipLevel←3 ⍝ default compression level (0-9)
|
|
||||||
|
|
||||||
⍝ Container-related settings
|
|
||||||
:Field Public DYALOG_JARVIS_THREAD←'' ⍝ 0 = Run in thread 0, 1 = Use separate thread and ⎕TSYNC, 'DEBUG' = Use separate thread and return to immediate execution, "AUTO" = if InTerm use "DEBUG" otherwise 1
|
|
||||||
:Field Public DYALOG_JARVIS_CODELOCATION←'' ⍝ If supplied, overrides CodeLocation in config file
|
|
||||||
:Field Public DYALOG_JARVIS_PORT←'' ⍝ If supplied, overrides Port both default port and config file
|
|
||||||
|
|
||||||
⍝ Session settings
|
|
||||||
:Field Public SessionIdHeader←'Jarvis-SessionID' ⍝ Name of the header field for the session token
|
|
||||||
:Field Public SessionUseCookie←0 ⍝ 0 - just use the header; 1 - use an HTTP cookie
|
|
||||||
:Field Public SessionPollingTime←1 ⍝ how frequently (in minutes) we should poll for timed out sessions
|
|
||||||
:Field Public SessionTimeout←0 ⍝ 0 = do not use sessions, ¯1 = no timeout , 0< session timeout time (in minutes)
|
|
||||||
:Field Public SessionCleanupTime←60 ⍝ how frequently (in minutes) do we clean up timed out session info from _sessionsInfo
|
|
||||||
|
|
||||||
⍝ JSON mode settings
|
|
||||||
:Field Public AllowFormData←0 ⍝ do we allow POST form data in JSON paradigm?
|
|
||||||
:Field Public AllowGETs←0 ⍝ do we allow calling endpoints with HTTP GETs?
|
|
||||||
:Field Public HTMLInterface←¯1 ⍝ ¯1=unassigned, 0/1=dis/allow the HTML interface, 'Path to HTML[/home-page]', or '' 'fn'
|
|
||||||
:Field Public JSONInputFormat←'D' ⍝ set this to 'M' to have Jarvis convert JSON request payloads to the ⎕JSON matrix format
|
|
||||||
|
|
||||||
⍝ REST mode settings
|
|
||||||
:Field Public ParsePayload←1 ⍝ 1=parse request payload based on content-type header (REST only)
|
|
||||||
:Field Public RESTMethods←'Get,Post,Put,Delete,Patch,Options'
|
|
||||||
|
|
||||||
⍝ CORS settings
|
|
||||||
:Field Public EnableCORS←1 ⍝ set to 0 to disable CORS
|
|
||||||
:Field Public CORS_Origin←'*' ⍝ default value for Access-Control-Allow-Origin header (set to 1 to reflect request Origin)
|
|
||||||
:Field Public CORS_Methods←¯1 ⍝ ¯1 = set based on paradigm, 1 = reflect the request's requested method
|
|
||||||
:Field Public CORS_Headers←'*' ⍝ default value for Access-Control-Allow-Headers header (set to 1 to reflect request Headers)
|
|
||||||
:Field Public CORS_MaxAge←60 ⍝ default value (in seconds) for Access-Control-Max-Age header
|
|
||||||
|
|
||||||
⍝ Conga-related settings
|
|
||||||
:Field Public AcceptFrom←⍬ ⍝ Conga: IP addresses to accept requests from - empty means accept from any IP address
|
|
||||||
:Field Public BufferSize←10000 ⍝ Conga: buffer size
|
|
||||||
:Field Public DenyFrom←⍬ ⍝ Conga: IP addresses to refuse requests from - empty means deny none
|
|
||||||
:Field Public DOSLimit←¯1 ⍝ Conga: DOSLimit, ¯1 means use default
|
|
||||||
:Field Public Port←8080 ⍝ Conga: Default port to listen on
|
|
||||||
:Field Public RootCertDir←'' ⍝ Conga: Root CA certificate folder
|
|
||||||
:field Public Priority←'NORMAL:!CTYPE-OPENPGP' ⍝ Conga: Priorities for GnuTLS when negotiation connection
|
|
||||||
:Field Public Secure←0 ⍝ 0 = use HTTP, 1 = use HTTPS
|
|
||||||
:field Public ServerCertSKI←'' ⍝ Conga: Server cert's Subject Key Identifier from store
|
|
||||||
:Field Public ServerCertFile←'' ⍝ Conga: public certificate file
|
|
||||||
:Field Public ServerKeyFile←'' ⍝ Conga: private key file
|
|
||||||
:Field Public ServerName←'' ⍝ Server name, '' means Conga assigns it
|
|
||||||
:Field Public SSLValidation←64 ⍝ Conga: request, but do not require a client certificate
|
|
||||||
:Field Public WaitTimeout←15000 ⍝ ms to wait in LDRC.Wait
|
|
||||||
|
|
||||||
:Field Public Shared LDRC←'' ⍝ Jarvis-set reference to Conga after CongaRef has been resolved
|
|
||||||
:Field Public Shared CongaPath←'' ⍝ user-supplied path to Conga workspace and/or shared libraries
|
|
||||||
:Field Public Shared CongaRef←'' ⍝ user-supplied reference to Conga library instance
|
|
||||||
:Field CongaVersion←'' ⍝ Conga version
|
|
||||||
|
|
||||||
:Property CodeSource
|
|
||||||
:Access Public
|
|
||||||
∇ r←get
|
|
||||||
r←_codeSource
|
|
||||||
∇
|
|
||||||
:EndProperty
|
|
||||||
|
|
||||||
⍝ IncludeFns/ExcludeFns Properties
|
|
||||||
:Property IncludeFns, ExcludeFns
|
|
||||||
⍝ IncludeFns and ExcludeFns are vectors the defined endpoint (function) names to expose or hide respectively
|
|
||||||
⍝ They can be function names, simple wildcarded patterns (e.g. 'Foo*'), or regex
|
|
||||||
:Access Public
|
|
||||||
∇ r←get ipa
|
|
||||||
r←⍎'_',ipa.Name
|
|
||||||
∇
|
|
||||||
∇ set ipa
|
|
||||||
:Select ipa.Name
|
|
||||||
:Case 'IncludeFns'
|
|
||||||
_includeRegex←makeRegEx¨(⊂'')~⍨∪,⊆_IncludeFns←ipa.NewValue
|
|
||||||
:Case 'ExcludeFns'
|
|
||||||
_excludeRegex←makeRegEx¨(⊂'')~⍨∪,⊆_ExcludeFns←ipa.NewValue
|
|
||||||
:EndSelect
|
|
||||||
∇
|
|
||||||
:EndProperty
|
|
||||||
|
|
||||||
⍝↓↓↓ some of these private fields are also set in ∇init so that a server can be stopped, updated, and restarted
|
|
||||||
:Field _rootFolder←'' ⍝ root folder for relative file paths
|
|
||||||
:Field _codeSource←'' ⍝ file or folder that code was loaded from, if applicable
|
|
||||||
:Field _configLoaded←0 ⍝ indicates whether config was already loaded by Autostart
|
|
||||||
:Field _htmlFolder←'' ⍝ folder containing HTML interface files, if any
|
|
||||||
:Field _htmlDefaultPage←'index.html' ⍝ default page name if HTMLInterface is set to serve from a folder
|
|
||||||
:Field _htmlEnabled←0 ⍝ is the HTML interface enabled?
|
|
||||||
:Field _htmlRootFn←'' ⍝ function name if serving HTML root from a function rather than file
|
|
||||||
:Field _stop←0 ⍝ set to 1 to stop server
|
|
||||||
:Field _started←0 ⍝ is the server started
|
|
||||||
:Field _stopped←1 ⍝ is the server stopped
|
|
||||||
:field _paused←0 ⍝ is the server paused
|
|
||||||
:Field _sessionThread←¯1 ⍝ thread for the session cleanup process
|
|
||||||
:Field _serverThread←¯1 ⍝ thread for the HTTP server
|
|
||||||
:Field _taskThreads←⍬ ⍝ vector of thread handling requests
|
|
||||||
:Field _sessions←⍬ ⍝ vector of session namespaces
|
|
||||||
:Field _sessionsInfo←0 5⍴'' '' 0 0 0 ⍝ [;1] id [;2] ip addr [;3] creation time [;4] last active time [;5] ref to session
|
|
||||||
:Field _IncludeFns←'' ⍝ private IncludeFns
|
|
||||||
:Field _ExcludeFns←'' ⍝ private ExcludeFns
|
|
||||||
:Field _includeRegex←'' ⍝ private compiled regex from _IncludeFns
|
|
||||||
:Field _excludeRegex←'' ⍝ private compiled regex from _ExcludeFns
|
|
||||||
:Field _connections ⍝ namespace containing open connections
|
|
||||||
|
|
||||||
∇ r←Config
|
∇ r←Config
|
||||||
⍝ returns current configuration
|
⍝ returns current configuration
|
||||||
:Access public
|
:Access public
|
||||||
|
@ -1713,33 +1581,6 @@ lam←{
|
||||||
∇
|
∇
|
||||||
|
|
||||||
:class Request
|
:class Request
|
||||||
:Field Public Instance AcceptEncodings←''⍝ content-encodings that the client will accept
|
|
||||||
:Field Public Instance Boundary←'' ⍝ boundary for content-type 'multipart/form-data'
|
|
||||||
:Field Public Instance Charset←'' ⍝ content charset (defaults to 'utf-8' if content-type is application/json)
|
|
||||||
:Field Public Instance Complete←0 ⍝ do we have a complete request?
|
|
||||||
:Field Public Instance ContentType←'' ⍝ content-type header value
|
|
||||||
:Field Public Instance Cookies←0 2⍴⊂'' ⍝ cookie name/value pairs
|
|
||||||
:Field Public Instance Input←''
|
|
||||||
:Field Public Instance Headers←0 2⍴⊂'' ⍝ HTTPRequest header fields (plus any supplied from HTTPTrailer event)
|
|
||||||
:Field Public Instance Method←'' ⍝ HTTP method (GET, POST, PUT, etc)
|
|
||||||
:Field Public Instance Endpoint←'' ⍝ Requested URI
|
|
||||||
:Field Public Instance Body←'' ⍝ body of the request
|
|
||||||
:Field Public Instance Payload←'' ⍝ parsed (if JSON or XML) payload
|
|
||||||
:Field Public Instance PeerAddr←'unknown'⍝ client IP address
|
|
||||||
:Field Public Instance PeerCert←0 0⍴⊂'' ⍝ client certificate
|
|
||||||
:Field Public Instance HTTPVersion←''
|
|
||||||
:Field Public Instance ErrorInfoLevel←1
|
|
||||||
:Field Public Instance Response
|
|
||||||
:Field Public Instance Server
|
|
||||||
:Field Public Instance Session←⍬
|
|
||||||
:Field Public Instance QueryParams←0 2⍴0
|
|
||||||
:Field Public Instance UserID←''
|
|
||||||
:Field Public Instance Password←''
|
|
||||||
:Field Public Shared HttpStatus←↑(200 'OK')(201 'Created')(204 'No Content')(301 'Moved Permanently')(302 'Found')(303 'See Other')(304 'Not Modified')(305 'Use Proxy')(307 'Temporary Redirect')(400 'Bad Request')(401 'Unauthorized')(403 'Forbidden')(404 'Not Found')(405 'Method Not Allowed')(406 'Not Acceptable')(408 'Request Timeout')(409 'Conflict')(410 'Gone')(411 'Length Required')(412 'Precondition Failed')(413 'Request Entity Too Large')(414 'Request-URI Too Long')(415 'Unsupported Media Type')(500 'Internal Server Error')(501 'Not Implemented')(503 'Service Unavailable')
|
|
||||||
|
|
||||||
⍝ Content types for common file extensions
|
|
||||||
:Field Public Shared ContentTypes←18 2⍴'txt' 'text/plain' 'htm' 'text/html' 'html' 'text/html' 'css' 'text/css' 'xml' 'text/xml' 'svg' 'image/svg+xml' 'json' 'application/json' 'zip' 'application/x-zip-compressed' 'csv' 'text/csv' 'pdf' 'application/pdf' 'mp3' 'audio/mpeg' 'pptx' 'application/vnd.openxmlformats-officedocument.presentationml.presentation' 'js' 'application/javascript' 'png' 'image/png' 'jpg' 'image/jpeg' 'bmp' 'image/bmp' 'jpeg' 'image/jpeg' 'woff' 'application/font-woff'
|
|
||||||
|
|
||||||
GetFromTable←{(⍵[;1]⍳⊂,⍺)⊃⍵[;2],⊂''}
|
GetFromTable←{(⍵[;1]⍳⊂,⍺)⊃⍵[;2],⊂''}
|
||||||
split←{p←(⍺⍷⍵)⍳1 ⋄ ((p-1)↑⍵)(p↓⍵)} ⍝ Split ⍵ on first occurrence of ⍺
|
split←{p←(⍺⍷⍵)⍳1 ⋄ ((p-1)↑⍵)(p↓⍵)} ⍝ Split ⍵ on first occurrence of ⍺
|
||||||
lc←0∘(819⌶)
|
lc←0∘(819⌶)
|
||||||
|
@ -1895,7 +1736,6 @@ lam←{
|
||||||
∇
|
∇
|
||||||
|
|
||||||
base64←{⎕IO ⎕ML←0 1 ⍝ from dfns workspace - Base64 encoding and decoding as used in MIME.
|
base64←{⎕IO ⎕ML←0 1 ⍝ from dfns workspace - Base64 encoding and decoding as used in MIME.
|
||||||
chars←'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
|
||||||
bits←{,⍉(⍺⍴2)⊤⍵} ⍝ encode each element of ⍵ in ⍺ bits, and catenate them all together
|
bits←{,⍉(⍺⍴2)⊤⍵} ⍝ encode each element of ⍵ in ⍺ bits, and catenate them all together
|
||||||
part←{((⍴⍵)⍴⍺↑1)⊂⍵} ⍝ partition ⍵ into chunks of length ⍺
|
part←{((⍴⍵)⍴⍺↑1)⊂⍵} ⍝ partition ⍵ into chunks of length ⍺
|
||||||
0=2|⎕DR ⍵:2∘⊥∘(8∘↑)¨8 part{(-8|⍴⍵)↓⍵}6 bits{(⍵≠64)/⍵}chars⍳⍵ ⍝ decode a string into octets
|
0=2|⎕DR ⍵:2∘⊥∘(8∘↑)¨8 part{(-8|⍴⍵)↓⍵}6 bits{(⍵≠64)/⍵}chars⍳⍵ ⍝ decode a string into octets
|
||||||
|
@ -1965,19 +1805,6 @@ lam←{
|
||||||
Response.Headers⍪←name(∊⍕value)
|
Response.Headers⍪←name(∊⍕value)
|
||||||
∇
|
∇
|
||||||
|
|
||||||
∇ {(name cookie)}←name SetCookie cookie
|
|
||||||
:Access public instance
|
|
||||||
⍝ create a response "set-cookie" header
|
|
||||||
⍝ cookie is the cookie value followed by any ;-delimited attributes
|
|
||||||
'set-cookie'SetHeader name,'=',cookie
|
|
||||||
∇
|
|
||||||
|
|
||||||
∇ {(name value)}←SetContentType contentType
|
|
||||||
:Access public instance
|
|
||||||
⍝ shortcut function to set the response content-type header
|
|
||||||
(name value)←'Content-Type'SetHeader contentType
|
|
||||||
∇
|
|
||||||
|
|
||||||
∇ value←GetCookie name
|
∇ value←GetCookie name
|
||||||
:Access public instance
|
:Access public instance
|
||||||
⍝ retrieve a request cookie
|
⍝ retrieve a request cookie
|
||||||
|
@ -2005,41 +1832,6 @@ lam←{
|
||||||
|
|
||||||
:Section SessionHandler
|
:Section SessionHandler
|
||||||
|
|
||||||
∇ InitSessions
|
|
||||||
⍝ initialize session handling
|
|
||||||
:If 0≠SessionTimeout ⍝ are we using sessions?
|
|
||||||
_sessions←⍬
|
|
||||||
_sessionsInfo←0 5⍴0 ⍝ [;1] id, [;2] IP address, [;3] creation time, [;4] last active time, [;5] ref to session
|
|
||||||
⎕RL←⍬
|
|
||||||
:If 0<SessionTimeout ⍝ is there a timeout set? 0> means no timeout and sessions are managed by the application
|
|
||||||
_sessionThread←SessionMonitor&SessionTimeout
|
|
||||||
:EndIf
|
|
||||||
:EndIf
|
|
||||||
∇
|
|
||||||
|
|
||||||
∇ SessionMonitor timeout;expired;dead
|
|
||||||
:Repeat
|
|
||||||
:If 0<≢_sessionsInfo
|
|
||||||
:Hold 'Sessions'
|
|
||||||
:If ∨/expired←SessionTimeout IsExpired _sessionsInfo[;4] ⍝ any expired?
|
|
||||||
⍝ ↓↓↓ if a session expires, remove the namespace from _sessions
|
|
||||||
⍝ but leave the entry in _sessionsInfo (removing the namespace reference)
|
|
||||||
⍝ so that we can report to the user that his session timed out
|
|
||||||
⍝ if he returns before SessionCleanupTime passes
|
|
||||||
_sessions~←expired/_sessionsInfo[;5] ⍝ remove from sessions list
|
|
||||||
(expired/_sessionsInfo[;5])←0 ⍝ remove reference from _sessionsInfo
|
|
||||||
:EndIf
|
|
||||||
⍝ ↓↓↓ SessionCleanupTime is used to clean up _sessionsInfo after a session has expired
|
|
||||||
⍝ In general SessionCleanupTime should be set to a value ≥ SessionTimeout
|
|
||||||
:If ∨/dead←(0=_sessionsInfo[;5])∧SessionCleanupTime IsExpired _sessionsInfo[;4] ⍝ any expired sessions need their info removed?
|
|
||||||
_sessionsInfo⌿⍨←~dead ⍝ remove from _sessionsInfo
|
|
||||||
:EndIf
|
|
||||||
:EndHold
|
|
||||||
:EndIf
|
|
||||||
{}⎕DL timeout×60
|
|
||||||
:EndRepeat
|
|
||||||
∇
|
|
||||||
|
|
||||||
MakeSessionId←{⎕IO←0 ⋄((0(819⌶)⎕A),⎕A,⎕D)[(?20⍴62),5↑1↓⎕TS]}
|
MakeSessionId←{⎕IO←0 ⋄((0(819⌶)⎕A),⎕A,⎕D)[(?20⍴62),5↑1↓⎕TS]}
|
||||||
IsExpired←{⍺≤0: 0 ⋄ (Now-⍵)>(⍺×60000)÷86400000}
|
IsExpired←{⍺≤0: 0 ⋄ (Now-⍵)>(⍺×60000)÷86400000}
|
||||||
|
|
||||||
|
@ -2048,92 +1840,6 @@ lam←{
|
||||||
r←(2 ⎕NQ'.' 'DateToIDN'(3↑ts))+(0 60 60 1000⊥¯4↑7↑ts)÷86400000
|
r←(2 ⎕NQ'.' 'DateToIDN'(3↑ts))+(0 60 60 1000⊥¯4↑7↑ts)÷86400000
|
||||||
∇
|
∇
|
||||||
|
|
||||||
∇ CreateSession req;ref;now;id;ts;rc
|
|
||||||
id←MakeSessionId''
|
|
||||||
now←Now
|
|
||||||
:Hold 'Sessions'
|
|
||||||
_sessions,←ref←⎕NS''
|
|
||||||
_sessionsInfo⍪←id req.PeerAddr now now ref
|
|
||||||
req.Session←ref
|
|
||||||
:EndHold
|
|
||||||
:If ~0∊⍴SessionInitFn
|
|
||||||
:If 3=CodeLocation.⎕NC SessionInitFn
|
|
||||||
:Trap 0 DebugLevel 1
|
|
||||||
:Trap 85
|
|
||||||
stopIf DebugLevel 2
|
|
||||||
rc←SessionInitFn CodeLocation.{1(85⌶)⍺,' ⍵'}req
|
|
||||||
:Else ⋄ rc←0
|
|
||||||
:EndTrap
|
|
||||||
|
|
||||||
:If 0≠rc
|
|
||||||
(_sessions _sessionsInfo)←¯1↓¨_sessions _sessionsInfo
|
|
||||||
→0⊣('Session intialization returned ',⍕rc)req.Fail 500
|
|
||||||
:EndIf
|
|
||||||
:Else
|
|
||||||
→0⊣(⎕DMX.EM,' occurred during session initialization failed')req.Fail 500
|
|
||||||
:EndTrap
|
|
||||||
:Else
|
|
||||||
→0⊣('Session initialization function "',SessionInitFn,'" not found')req.Fail 500
|
|
||||||
:EndIf
|
|
||||||
:EndIf
|
|
||||||
:If SessionUseCookie
|
|
||||||
SessionIdHeader req.SetCookie id,(SessionTimeout>0)/'; Max-Age=',⍕⌈60×SessionTimeout
|
|
||||||
:Else
|
|
||||||
SessionIdHeader req.SetHeader id
|
|
||||||
:EndIf
|
|
||||||
∇
|
|
||||||
|
|
||||||
∇ r←KillSession id;ind
|
|
||||||
⍝ forcibly kill a session
|
|
||||||
⍝ r is 1 if session was killed, 0 if not found
|
|
||||||
:Hold 'Sessions'
|
|
||||||
:If r←(≢_sessionsInfo)≥ind←_sessionsInfo[;1]⍳⊆id
|
|
||||||
_sessions~←_sessionsInfo[ind;5]
|
|
||||||
_sessionsInfo⌿⍨←ind≠⍳≢_sessionsInfo
|
|
||||||
:EndIf
|
|
||||||
:EndHold
|
|
||||||
∇
|
|
||||||
|
|
||||||
∇ req TimeoutSession ind
|
|
||||||
⍝ assumes :Hold 'Sessions' is set in calling environment
|
|
||||||
⍝ removes session from _sessions and marks it as time out in _sessionsInfo
|
|
||||||
_sessions~←_sessionsInfo[ind;5]
|
|
||||||
_sessionsInfo⌿←ind≠⍳≢_sessionsInfo
|
|
||||||
∇
|
|
||||||
|
|
||||||
∇ id←GetSessionId req
|
|
||||||
:If SessionUseCookie
|
|
||||||
id←req.GetCookie SessionIdHeader
|
|
||||||
:Else
|
|
||||||
id←req.GetHeader SessionIdHeader
|
|
||||||
:EndIf
|
|
||||||
∇
|
|
||||||
|
|
||||||
∇ r←CheckSession req;ind;session;timedOut;id
|
|
||||||
⍝ check for valid session (only called if SessionTimeout≠0)
|
|
||||||
r←1
|
|
||||||
:Hold 'Sessions'
|
|
||||||
id←GetSessionId req
|
|
||||||
ind←_sessionsInfo[;1]⍳⊂id
|
|
||||||
→0⍴⍨ind>≢_sessionsInfo
|
|
||||||
|
|
||||||
:If 0∊⍴session←⊃_sessionsInfo[ind;5] ⍝ already timed out (session was already removed from _sessions)
|
|
||||||
:OrIf SessionTimeout IsExpired _sessionsInfo[ind;4] ⍝ newly expired
|
|
||||||
req TimeoutSession ind
|
|
||||||
→0
|
|
||||||
:EndIf
|
|
||||||
⍝ we have a valid session, refresh the cookie or set the header
|
|
||||||
:If SessionUseCookie
|
|
||||||
SessionIdHeader req.SetCookie id,(SessionTimeout>0)/'; Max-Age=',⍕⌈60×SessionTimeout
|
|
||||||
:ElseIf
|
|
||||||
SessionIdHeader req.SetHeader id
|
|
||||||
:EndIf
|
|
||||||
_sessionsInfo[ind;4]←Now
|
|
||||||
req.Session←session
|
|
||||||
r←0
|
|
||||||
:EndHold
|
|
||||||
∇
|
|
||||||
|
|
||||||
:EndSection
|
:EndSection
|
||||||
|
|
||||||
:Section Utilities
|
:Section Utilities
|
||||||
|
@ -2154,10 +1860,6 @@ lam←{
|
||||||
sins←{0∊⍴⍺:⍵ ⋄ ⍺} ⍝ set if not set
|
sins←{0∊⍴⍺:⍵ ⋄ ⍺} ⍝ set if not set
|
||||||
stopIf←{1∊⍵:-⎕TRAP←0 'C' '⎕←''Stopped for debugging... (Press Ctrl-Enter)''' ⋄ shy←0} ⍝ faster alternative to setting ⎕STOP
|
stopIf←{1∊⍵:-⎕TRAP←0 'C' '⎕←''Stopped for debugging... (Press Ctrl-Enter)''' ⋄ shy←0} ⍝ faster alternative to setting ⎕STOP
|
||||||
show←{(2⊃⎕SI),'[',(⍕2⊃⎕LC),'] ',⍵} ⍝ debugging utility
|
show←{(2⊃⎕SI),'[',(⍕2⊃⎕LC),'] ',⍵} ⍝ debugging utility
|
||||||
utf8←{3=10|⎕DR ⍵: 256|⍵ ⋄ 'UTF-8' ⎕UCS ⍵}
|
|
||||||
fromutf8←{0::(⎕AV,'?')[⎕AVU⍳⍵] ⋄ 'UTF-8'⎕UCS ⍵} ⍝ Turn raw UTF-8 input into text
|
|
||||||
sint←{⎕IO←0 ⋄ 83=⎕DR ⍵:⍵ ⋄ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 ¯128 ¯127 ¯126 ¯125 ¯124 ¯123 ¯122 ¯121 ¯120 ¯119 ¯118 ¯117 ¯116 ¯115 ¯114 ¯113 ¯112 ¯111 ¯110 ¯109 ¯108 ¯107 ¯106 ¯105 ¯104 ¯103 ¯102 ¯101 ¯100 ¯99 ¯98 ¯97 ¯96 ¯95 ¯94 ¯93 ¯92 ¯91 ¯90 ¯89 ¯88 ¯87 ¯86 ¯85 ¯84 ¯83 ¯82 ¯81 ¯80 ¯79 ¯78 ¯77 ¯76 ¯75 ¯74 ¯73 ¯72 ¯71 ¯70 ¯69 ¯68 ¯67 ¯66 ¯65 ¯64 ¯63 ¯62 ¯61 ¯60 ¯59 ¯58 ¯57 ¯56 ¯55 ¯54 ¯53 ¯52 ¯51 ¯50 ¯49 ¯48 ¯47 ¯46 ¯45 ¯44 ¯43 ¯42 ¯41 ¯40 ¯39 ¯38 ¯37 ¯36 ¯35 ¯34 ¯33 ¯32 ¯31 ¯30 ¯29 ¯28 ¯27 ¯26 ¯25 ¯24 ¯23 ¯22 ¯21 ¯20 ¯19 ¯18 ¯17 ¯16 ¯15 ¯14 ¯13 ¯12 ¯11 ¯10 ¯9 ¯8 ¯7 ¯6 ¯5 ¯4 ¯3 ¯2 ¯1[utf8 ⍵]}
|
|
||||||
Zipper←219⌶
|
|
||||||
|
|
||||||
∇ r←DyalogRoot
|
∇ r←DyalogRoot
|
||||||
r←{⍵,('/\'∊⍨⊢/⍵)↓'/'}{0∊⍴t←2 ⎕NQ'.' 'GetEnvironment' 'DYALOG':⊃1 ⎕NPARTS⊃2 ⎕NQ'.' 'GetCommandLineArgs' ⋄ t}''
|
r←{⍵,('/\'∊⍨⊢/⍵)↓'/'}{0∊⍴t←2 ⎕NQ'.' 'GetEnvironment' 'DYALOG':⊃1 ⎕NPARTS⊃2 ⎕NQ'.' 'GetCommandLineArgs' ⋄ t}''
|
||||||
|
@ -2172,15 +1874,6 @@ lam←{
|
||||||
:EndTrap
|
:EndTrap
|
||||||
∇
|
∇
|
||||||
|
|
||||||
∇ r←crlf
|
|
||||||
r←⎕UCS 13 10
|
|
||||||
∇
|
|
||||||
|
|
||||||
∇ QuadOFF
|
|
||||||
⍝ cover for ⎕OFF in case we want to add debugging
|
|
||||||
⎕OFF
|
|
||||||
∇
|
|
||||||
|
|
||||||
∇ r←Now
|
∇ r←Now
|
||||||
r←DateToIDNX ⎕TS
|
r←DateToIDNX ⎕TS
|
||||||
∇
|
∇
|
||||||
|
@ -2324,9 +2017,6 @@ lam←{
|
||||||
∇
|
∇
|
||||||
|
|
||||||
Deserialise←{
|
Deserialise←{
|
||||||
⍝ copied (and modified to work here) from
|
|
||||||
⍝ https://github.com/Dyalog/qSE/tree/db88297980476d81e0122624ecaa246c94149555
|
|
||||||
|
|
||||||
⍝ Convert text to array
|
⍝ Convert text to array
|
||||||
⍺←⍬ ⍝ 1=execute expression; 0=return expression
|
⍺←⍬ ⍝ 1=execute expression; 0=return expression
|
||||||
⎕IO←0
|
⎕IO←0
|
||||||
|
@ -2389,21 +2079,6 @@ lam←{
|
||||||
assns/⍨←~quadMask
|
assns/⍨←~quadMask
|
||||||
∊'({'(assns,¨'⋄')quadAssns'⎕NS'('(, '∘,¨q,¨names,¨⊂q')')'}⍬)'
|
∊'({'(assns,¨'⋄')quadAssns'⎕NS'('(, '∘,¨q,¨names,¨⊂q')')'}⍬)'
|
||||||
}
|
}
|
||||||
Execute←{ ⍝ overcome LIMIT ERROR on more than 4096 parenthesised expressions
|
|
||||||
ExecuteEach←{ ⍝ split at level-1 parentheses and execute each
|
|
||||||
l←(t=¯1)++\t←{1 ¯1 0['()'⍳⍵]}Unquot ⍵ ⍝ parenthesis type and level
|
|
||||||
(h x t l)←(1 0 0 0=⊂∧\l=0)/¨⍵ ⍵ t l ⍝ extract header before first opening parenthesis
|
|
||||||
⍺{0::0 ⋄ r←⍺⍎⍵ ⋄ ~(⊃⎕NC'r')∊3 4}h:⍺⍎⍵ ⍝ header must be an functional expression
|
|
||||||
H←⍺{⍺⍺⍎⍵⍵,'⍵'}h ⍝ function to apply header to array
|
|
||||||
' '∨.≠(l=0)/x:⍺⍎⍵ ⍝ something outside level-1 parentheses - must fall back to ⍎
|
|
||||||
x←(((l>0)∧(l≠1)∨(t=0))×+\(t=1)∧(l=1))⊆x ⍝ cut expression within level-1 parentheses
|
|
||||||
1=≢x:H ⍺ ∇⊃x ⍝ single expression : don't enclose with ¨
|
|
||||||
DEBUG∧1<⌈/l:H ⍺ ∇¨x ⍝ force going through the hard code
|
|
||||||
10::H ⍺ ∇¨x ⋄ H ⍺⍎¨x ⍝ attempt to ⍎¨ with a single guard - otherwise dig each
|
|
||||||
}
|
|
||||||
DEBUG:⍺ ExecuteEach ⍵ ⍝ force going through the hard code
|
|
||||||
10::⍺ ExecuteEach ⍵ ⋄ ⍺⍎⍵ ⍝ attempt simple ⍎ and catch LIMIT ERROR
|
|
||||||
}
|
|
||||||
⍝ Make normalised simple vector:
|
⍝ Make normalised simple vector:
|
||||||
w←↓⍣(2=≢⍴⍵)⊢⍵ ⍝ if mat, make nested
|
w←↓⍣(2=≢⍴⍵)⊢⍵ ⍝ if mat, make nested
|
||||||
w←{¯1↓∊⍵,¨⎕UCS 13}⍣(2=|≡w)⊢w ⍝ if nested, make simple
|
w←{¯1↓∊⍵,¨⎕UCS 13}⍣(2=|≡w)⊢w ⍝ if nested, make simple
|
||||||
|
@ -2438,84 +2113,6 @@ lam←{
|
||||||
∇ r←HtmlPage;endpoints
|
∇ r←HtmlPage;endpoints
|
||||||
:Access public
|
:Access public
|
||||||
r←ScriptFollows
|
r←ScriptFollows
|
||||||
⍝<!DOCTYPE html>
|
|
||||||
⍝<html>
|
|
||||||
⍝<head>
|
|
||||||
⍝<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
|
||||||
⍝<link rel="icon" href="data:,">
|
|
||||||
⍝<title>Jarvis</title>
|
|
||||||
⍝ <style>
|
|
||||||
⍝ body {color:#000000;background-color:white;font-family:Verdana;margin-left:0px;margin-top:0px;}
|
|
||||||
⍝ button {display:inline-block;font-size:1.1em;}
|
|
||||||
⍝ legend {font-size:1.1em;}
|
|
||||||
⍝ select {font-size:1.1em;}
|
|
||||||
⍝ label {display:inline-block;margin-bottom:7px;}
|
|
||||||
⍝ div {padding:5px;}
|
|
||||||
⍝ label input textarea button #result {display:flex;}
|
|
||||||
⍝ textarea {width:100%;font-size:18px;}
|
|
||||||
⍝ #result {font-size:18px;}
|
|
||||||
⍝ #result code {white-space:pre-line;word-wrap:break-word;}
|
|
||||||
⍝ </style>
|
|
||||||
⍝</head>
|
|
||||||
⍝<body>
|
|
||||||
⍝<div id="content">
|
|
||||||
⍝<fieldset>
|
|
||||||
⍝ <legend>Request</legend>
|
|
||||||
⍝ <form id="myform">
|
|
||||||
⍝ <div>
|
|
||||||
⍝ <label for="function">Endpoint:</label>
|
|
||||||
⍝ ⍠
|
|
||||||
⍝ </div>
|
|
||||||
⍝ <div>
|
|
||||||
⍝ <label for="payload">JSON Payload:</label>
|
|
||||||
⍝ <textarea id="payload" name="payload"></textarea>
|
|
||||||
⍝ </div>
|
|
||||||
⍝ <div>
|
|
||||||
⍝ <button onclick="doit()" type="button">Send</button>
|
|
||||||
⍝ </div>
|
|
||||||
⍝ </form>
|
|
||||||
⍝</fieldset>
|
|
||||||
⍝<fieldset>
|
|
||||||
⍝ <legend>Response</legend>
|
|
||||||
⍝ <div id="result">
|
|
||||||
⍝ </div>
|
|
||||||
⍝</fieldset>
|
|
||||||
⍝<script>
|
|
||||||
⍝function doit() {
|
|
||||||
⍝ document.getElementById("result").innerHTML = "";
|
|
||||||
⍝ var payload = document.getElementById("payload").value;
|
|
||||||
⍝ if (0 == payload.length) {
|
|
||||||
⍝ document.getElementById("result").innerHTML = "<span style='color:red;'>Please enter a valid JSON payload</span>";
|
|
||||||
⍝ } else {
|
|
||||||
⍝ var xhttp = new XMLHttpRequest();
|
|
||||||
⍝ var fn = document.getElementById("function").value;
|
|
||||||
⍝ fn = (0 == fn.indexOf('/')) ? fn : '/' + fn;
|
|
||||||
⍝
|
|
||||||
⍝ xhttp.open("POST", fn, true);
|
|
||||||
⍝ xhttp.setRequestHeader("content-type", "application/json; charset=utf-8");
|
|
||||||
⍝
|
|
||||||
⍝ xhttp.onreadystatechange = function() {
|
|
||||||
⍝ if (this.readyState == 4){
|
|
||||||
⍝ if (this.status == 200) {
|
|
||||||
⍝ try {
|
|
||||||
⍝ var resp = "<pre><code>" + JSON.stringify(JSON.parse(this.responseText)) + "</code></pre>";;
|
|
||||||
⍝ }
|
|
||||||
⍝ catch(err) {
|
|
||||||
⍝ var resp = "<pre><code>" + this.responseText + "</code></pre>";
|
|
||||||
⍝ }
|
|
||||||
⍝ } else {
|
|
||||||
⍝ var resp = "<span style='color:red;'>" + this.statusText + "</span> <pre><code>" + this.responseText + "</code></pre>";
|
|
||||||
⍝ }
|
|
||||||
⍝ document.getElementById("result").innerHTML = resp;
|
|
||||||
⍝ }
|
|
||||||
⍝ }
|
|
||||||
⍝ xhttp.send(document.getElementById("payload").value);
|
|
||||||
⍝ }
|
|
||||||
⍝}
|
|
||||||
⍝</script>
|
|
||||||
⍝</div>
|
|
||||||
⍝</body>
|
|
||||||
⍝</html>
|
|
||||||
endpoints←{⍵/⍨0=CheckFunctionName ⍵}EndPoints CodeLocation
|
endpoints←{⍵/⍨0=CheckFunctionName ⍵}EndPoints CodeLocation
|
||||||
:If 0∊⍴endpoints
|
:If 0∊⍴endpoints
|
||||||
endpoints←'<b>No Endpoints Found</b>'
|
endpoints←'<b>No Endpoints Found</b>'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user