Protected Scripts

One of the goals of #Script is that its defaults should be safe enough to be able to execute arbitrary scripts by untrusted 3rd parties. Given this constraint, only default scripts are pre-registered which contain a comprehensive set of filters we deem safe for use by anyone. Other methods available in #Script which are useful to have in a server-generated website environment but we don't want 3rd Parties to access are filters in ProtectedScripts.cs.

ProtectedScripts are not pre-registered when creating a new ScriptContext but they are pre-registered when registering the SharpPagesFeature ServiceStack Plugin as that's designed to use #Script within a View Engine where access to its context is limited to the server's Web Application.

To access ProtectedScripts features within your own ScriptContext it can be registered like any other filter:

var context = new ScriptContext
{
    ScriptMethods = { new ProtectedScripts() }
}.Init();

includeFile

fileContents

Use includeFile to embed content directly within pages:

page.html
my-file.txt
Cascading resolution

If an exact match isn't found it will look for the closest file with that name it can find, starting from the directory where the containing page that uses the filter is located and traversing up until it reaches the root folder.

includeFileWithCache

fileContentsWithCache

If your VirtualFiles is configured to use a combination of various sources that includes a remote file service like S3VirtualFiles, you'll likely want to cache the contents in memory to ensure fast subsequent access the next time the file is requested, which you can cache without expiration using includeFileWithCache without arguments:

{{ 'my-file.txt' | includeFileWithCache }}

In which case it will use the 1 minute default overridable in Args[DefaultFileCacheExpiry] or if you want the content to be refreshed after 1hr you can use:

{{ 'my-file.txt' | includeFileWithCache({ expiresInSecs: 3600 }) }}

includeUrl

urlContents

You can also embed the contents of remote URLs in your page using includeUrl:

page.html

includeUrl is actually a very flexible HTTP Client which can leverage the URL Handling filters to easily construct urls and the additional filter arguments to customize the HTTP Request that's sent, here are some examples:

Accept JSON responses:

{{ url | includeUrl({ accept: 'application/json' }) }}
{{ url | includeUrl({ dataType: 'json' }) }}

Send data as form-urlencoded in a HTTP PUT Request with a #Script User-Agent:

{{ url | includeUrl({ method:'PUT', data: { id: 1, name: 'foo' }, userAgent:"#Script" }) }}

Send data as JSON in a HTTP POST request and Accept JSON response:

{{ url | includeUrl({ method: 'POST', data: { id: 1, name: 'foo' }, 
                      accept: 'application/json', contentType: 'application/json' }) }}

Shorter version of above request:

{{ url | includeUrl({ method:'POST', data: { id: 1, name: 'foo' }, dataType: 'json' }) }}

Send data as CSV in a HTTP POST Request and Accept a CSV response:

includeUrl({ method:'POST', data: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }], dataType:'csv' })

includeUrlWithCache

urlContentsWithCache

In the same way includeFileWithCache can cache file contents, includeUrlWithCache can cache URL content, either without an expiration:

{{ url | includeUrlWithCache }}

In which case it will use the 1 minute default overridable in Args[DefaultUrlCacheExpiry] or if you want to ensure that no more than 1 url request is made per hour for this url you can specify a custom expiry with:

{{ url | includeUrlWithCache({ expiresInSecs: 3600 }) }}

Virtual File System APIs

The Virtual File System APIs are mapped to the following methods:

All Protected Scripts Virtual File System APIs are executed against the ScriptContext.VirtualFiles which in #Script Pages is configured to the WebRoot FileSystem by default:

allFiles()

The VFS APIs utilizes Extension methods support to include an overloaded method that includes IVirtualPathProvider as its first argument:

public IEnumerable<IVirtualFile> allFiles() => allFiles(VirtualFiles);
public IEnumerable<IVirtualFile> allFiles(IVirtualPathProvider vfs) => vfs.GetAllFiles();

This allows being able to use the same method name against any VFS provider by calling it like an instance method, e.g:

vfsFileSystem(dirPath) | to => fs

fs.allFiles()

This is supported on all VFS APIs with its C# implementation where vfs is an instance of IVirtualPathProvider:

Protected VFS Script Method C# Implementation
allFiles() vfs.GetAllFiles()
allRootFiles() vfs.GetRootFiles()
allRootDirectories() vfs.GetRootDirectories()
dir(virtualPath) vfs.GetDirectory(virtualPath)
dirExists(virtualPath) vfs.DirectoryExists(virtualPath)
dirFile(dirPath, fileName) vfs.GetDirectory(dirPath)?.GetFile(fileName)
dirFiles(virtualPath) vfs.GetDirectory(dirPath)?.GetFiles()
dirDirectory(dirPath, dirName) vfs.GetDirectory(dirPath)?.GetDirectory(dirName)
dirDirectories(dirPath) vfs.GetDirectory(dirPath)?.GetDirectories()
findFilesInDirectory(dirPath, globPattern) vfs.GetDirectory(dirPath)?.GetAllMatchingFiles(globPattern)
findFiles(globPattern) vfs.GetAllMatchingFiles(globPattern)
fileExists(virtualPath) vfs.FileExists(virtualPath)
file(virtualPath) vfs.GetFile(virtualPath)
writeFile(virtualPath, contents) vfs.WriteFile(virtualPath, contents)
writeFiles(files) vfs.WriteFiles(files)
writeTextFiles(textFiles) vfs.WriteFiles(textFiles)
appendToFile(virtualPath, contents) vfs.AppendFile(virtualPath, contents)
deleteFile(virtualPath) vfs.DeleteFile(virtualPath)
deleteDirectory(virtualPath) vfs.DeleteFolder(virtualPath)
fileTextContents(virtualPath) vfs.GetFile(virtualPath)?.ReadAllText()
fileBytesContent(virtualPath) vfs.GetFile(virtualPath)?.ReadAllBytes()
fileHash(virtualPath) vfs.GetFileHash(virtualPath)

All above VFS APIs work against the built-in VFS providers below:

vfsMemory()                  | to => memFs
vfsFileSystem(dirPath)       | to => fs
vfsGist(gistId, accessToken) | to => gistFs
vfsGist(gistId)              | to => gistReadOnlyFs

They can also be used against AWS S3 and Azure Blob storage providers if you configure your ScriptContext with AwsScripts from ServiceStack.Aws package or AzureScripts from ServiceStack.Azure:

vfsS3(accessKey, secretAccessKey, region, bucketName) | to => s3Fs
vfsAzureBlob(connectionString, containerName)         | to => azureBlobFs

See the Scripts API Reference for the full list of ServiceStack scripts available.

made with by ServiceStack