234 attempt to fix js error Uncaught SyntaxError: Unexpected identifier 'hidden'
This commit is contained in:
+178
-41
@@ -12,7 +12,7 @@ The REST Web Service framework for ColdFusion and Lucee
|
||||
|
||||
**Application.cfc:**
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
component extends="taffy.core.api" {}
|
||||
```
|
||||
|
||||
@@ -24,7 +24,7 @@ component extends="taffy.core.api" {}
|
||||
|
||||
**/resources/hello.cfc:**
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
component extends="taffy.core.resource" taffy_uri="/hello" {
|
||||
|
||||
function get(){
|
||||
@@ -75,15 +75,19 @@ Using sub-folders requires the use of Application-Specific Mappings (introduced
|
||||
|
||||
You can see that the taffy folder is a sibling to Application.cfc. This allows Application.cfc to use relative paths to extend `taffy.core.api`.
|
||||
|
||||
Next, if your Application.cfc and `/resources/` folder aren't in the web-root (e.g. they're inside something like `/api/`) then you'll need to add an [application-specific mapping](http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=appFramework_04.html) for `/resources` so that Taffy can find your resources to initialize the routes.
|
||||
Next, if your Application.cfc and `/resources/` folder aren't in the web-root (e.g. they're inside something like `/api/`) then you'll need to do one of the following:
|
||||
|
||||
```js
|
||||
this.mappings["/resources"] = expandPath("./resources");
|
||||
```
|
||||
- Add an [application-specific mapping](http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=appFramework_04.html) for `/resources` so that Taffy can find your resources to initialize the routes.
|
||||
|
||||
```cfscript
|
||||
this.mappings["/resources"] = expandPath("../api/resources");
|
||||
```
|
||||
|
||||
- You can specify the path to your resource components using the [`resourcesCFCPath`](#resourcescfcpath) setting to specify the dotted path to your resource folder. This will allow you to store your resource components in the directory of your choosing.
|
||||
|
||||
You'll also need to add a mapping for `/taffy` so that the resources can extend `taffy.core.resource` (since the taffy folder isn't a child of the resources folder):
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
this.mappings["/taffy"] = expandPath("./taffy");
|
||||
```
|
||||
|
||||
@@ -132,7 +136,7 @@ In the xml above you can see that I only have 1 wildcard, but to compensate I've
|
||||
|
||||
Taffy allows for setting the HTTP status message using [.withStatus()](#withstatus), such as:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return representationOf({...}).withStatus(403, "Not Authorized");
|
||||
```
|
||||
|
||||
@@ -173,6 +177,54 @@ _Thanks to Brook Davies for providing the solution!_
|
||||
|
||||
Not all HTTP clients will allow you to easily send PUT or DELETE requests (sometimes not at all). The standard method for circumventing this restriction, which Taffy supports, is by sending your request as a POST with the header `X-HTTP-METHOD-OVERRIDE` and setting its value to PUT/DELETE as needed. Taffy will detect this header and treat the request as if it were a PUT/DELETE request.
|
||||
|
||||
## OpenAPI / Swagger
|
||||
|
||||
**Available in:** Taffy 4.0+
|
||||
|
||||
Taffy generates an [OpenAPI 3.1](https://spec.openapis.org/oas/v3.1.0) document describing your API automatically, using the same resource/argument metadata that powers the dashboard and docs. No extra annotations required — just hit:
|
||||
|
||||
- `index.cfm?openapi` — returns the spec as `application/json`
|
||||
- `index.cfm?swagger` — alias for the same endpoint
|
||||
|
||||
The generated document can be dropped into [Swagger UI](https://swagger.io/tools/swagger-ui/), [Stoplight Studio](https://stoplight.io/studio), Postman, [swagger.io Editor](https://editor.swagger.io/), or any other OpenAPI-aware tool.
|
||||
|
||||
### What gets generated
|
||||
|
||||
| OpenAPI field | Source |
|
||||
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| `info.title` | `variables.framework.docs.APIName` |
|
||||
| `info.version` | `variables.framework.docs.APIVersion` |
|
||||
| `info.description` / `contact` / `license` | `variables.framework.openapi` (optional) |
|
||||
| `servers[0].url` | Auto-derived from `cgi.http_host` + script path (override via `openapi.servers`) |
|
||||
| `paths` | Each resource's `taffy:uri` |
|
||||
| `operationId` | `{beanName}_{verb}` |
|
||||
| `summary` / `tags` | `taffy:docs:name` if set, else the bean name |
|
||||
| `description` | Function `hint` |
|
||||
| `parameters` (path) | URI tokens — always emitted, even if the resource doesn't declare them as args |
|
||||
| `parameters` (query) | Non-token args on `GET`/`DELETE`/`HEAD`/`OPTIONS` methods |
|
||||
| `requestBody` | Non-token args on `POST`/`PUT`/`PATCH` — emitted under both `application/json` and `application/x-www-form-urlencoded` |
|
||||
| Parameter `schema.type` / `format` | Mapped from the CFML arg `type` (`numeric`, `boolean`, `date`, `uuid`, etc.) |
|
||||
| Parameter `description` | Argument `hint` |
|
||||
| Parameter `default` | Argument `default` (when non-empty) |
|
||||
| Response content types | MIME types from all registered serializers (via `taffy:mime`) |
|
||||
|
||||
### Hiding things from the spec
|
||||
|
||||
The same metadata flags that hide resources from the dashboard also hide them from the OpenAPI spec:
|
||||
|
||||
- `taffy:docs:hide` / `taffy_docs_hide` — component, function, or argument
|
||||
- `taffy:dashboard:hide` / `taffy_dashboard_hide` — component, function, or argument
|
||||
|
||||
Custom `taffy:verb` values (anything outside the standard `get`/`put`/`post`/`delete`/`options`/`head`/`patch`/`trace`) are silently dropped — OpenAPI doesn't accept arbitrary verb names.
|
||||
|
||||
### Performance
|
||||
|
||||
The spec is generated once on the first request to `?openapi` (or `?swagger`) and cached in `application._taffy`. Subsequent requests serve the cached JSON string directly — no CFC instantiation, no metadata walking, no serialization. The cache is invalidated automatically on framework reload.
|
||||
|
||||
### Configuration
|
||||
|
||||
See [openapi](#openapi) below for the full config reference.
|
||||
|
||||
## More Guides
|
||||
|
||||
Some guides are too broad for this document. For your benefit, they are linked here:
|
||||
@@ -221,7 +273,7 @@ If you want a resource not to be included in the dashboard, set `taffy:dashboard
|
||||
|
||||
or
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
component taffy_uri="/secret-squirrel" taffy_dashboard_hide {
|
||||
}
|
||||
```
|
||||
@@ -247,7 +299,7 @@ The **taffy:uri** property applies to the `<cfcomponent>` tag or the `component{
|
||||
|
||||
or
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
component taffy_uri="/artist/{artistId}" {
|
||||
}
|
||||
```
|
||||
@@ -278,7 +330,7 @@ By convention, resources will automatically map the 4 primary HTTP REST verbs --
|
||||
|
||||
or
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
function getUser( numeric userId ) taffy_verb="get" {
|
||||
}
|
||||
```
|
||||
@@ -294,7 +346,7 @@ You can prevent a resource from showing in the documentation by adding the `taff
|
||||
|
||||
or
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
component extends="taffy.core.resource" taffy_uri="/artist/{artistId}" taffy_docs_hide {
|
||||
}
|
||||
```
|
||||
@@ -310,7 +362,7 @@ Similarly, you can hide methods and parameters by adding the attribute to the `<
|
||||
|
||||
or
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
public function getUser(
|
||||
required numeric userId,
|
||||
string _hidden = "" taffy_docs_hide
|
||||
@@ -320,6 +372,27 @@ taffy_docs_hide
|
||||
}
|
||||
```
|
||||
|
||||
##### Argument Constraint Metadata
|
||||
|
||||
You can document value constraints on function arguments using the following metadata attributes. These are **documentation-only** — Taffy does not enforce them at runtime, but they are displayed on the dashboard and generated docs as inline badges next to the argument name.
|
||||
|
||||
| Attribute | Applies to | Description |
|
||||
| ----------------- | ---------- | ---------------------------------- |
|
||||
| `taffy_minlength` | string | Minimum string length |
|
||||
| `taffy_maxlength` | string | Maximum string length |
|
||||
| `taffy_min` | numeric | Minimum numeric value |
|
||||
| `taffy_max` | numeric | Maximum numeric value |
|
||||
| `taffy_pattern` | string | Regex pattern the value must match |
|
||||
|
||||
```cfscript
|
||||
function get(
|
||||
required string changedOnDate = "" taffy_minlength="10" taffy_maxlength="10" taffy_pattern="^\d{4}-\d{2}-\d{2}$",
|
||||
numeric page = 1 taffy_min="1",
|
||||
numeric pageSize = 25 taffy_min="1" taffy_max="100"
|
||||
) {
|
||||
}
|
||||
```
|
||||
|
||||
#### In Serializers
|
||||
|
||||
Serializers are used to take the data provided by a resource and serialize it into a format usable by the web service consumer. A single Serializer is capable of serializing native data objects (strings, numbers, queries, structures, arrays, etc) into 1 or more formats. Typical formats include JSON, XML, or YAML, but are not limited.
|
||||
@@ -335,7 +408,7 @@ By convention, the mime-types supported by your API are determined by the method
|
||||
|
||||
or
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
function getAsJson() taffy_mime="application/json" {
|
||||
}
|
||||
```
|
||||
@@ -354,7 +427,7 @@ When your API supports more than one data format (i.e. json and xml), you must s
|
||||
|
||||
or
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
function getAsJson() taffy_mime="application/json" taffy_default="true" {}
|
||||
|
||||
function getAsXml() taffy_mime="application/xml" {}
|
||||
@@ -364,8 +437,9 @@ function getAsXml() taffy_mime="application/xml" {}
|
||||
|
||||
Default values:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
variables.framework = {
|
||||
resourcesCFCPath = "",
|
||||
reloadKey = "reload",
|
||||
reloadPassword = "true",
|
||||
reloadOnEveryRequest = false,
|
||||
@@ -382,6 +456,7 @@ variables.framework = {
|
||||
disabledDashboardRedirect = "",
|
||||
dashboardHeaders = {},
|
||||
showDocsWhenDashboardDisabled = false,
|
||||
allowGoogleFonts = true,
|
||||
docs = {
|
||||
APIName = "",
|
||||
APIVersion = ""
|
||||
@@ -396,21 +471,33 @@ variables.framework = {
|
||||
|
||||
unhandledPaths = "/flex2gateway",
|
||||
allowCrossDomain = false,
|
||||
exposeTaffyHeaders = true,
|
||||
globalHeaders = structNew(),
|
||||
debugKey = "debug",
|
||||
|
||||
useEtags = false,
|
||||
|
||||
returnExceptionsAsJson = true,
|
||||
returnExceptionsAsJson = false,
|
||||
exceptionLogAdapter = "taffy.bonus.LogToScreen",
|
||||
exceptionLogAdapterConfig = {},
|
||||
|
||||
beanFactory = "",
|
||||
|
||||
openapi = {
|
||||
enabled = true
|
||||
},
|
||||
|
||||
environments = {}
|
||||
};
|
||||
```
|
||||
|
||||
#### resourcesCFCPath
|
||||
|
||||
**Available in:** Taffy 3.8+<br/>
|
||||
**Type:** String<br/>
|
||||
**Default:** ""<br/>
|
||||
**Description:** By default, Taffy will attempt to load your resource components from either a child folder named `resources` or from a CF mapping named `resources`. You can use this setting to define an explicit path to your resource components using the "dotted" path of your resource folder (e.g. `myapp.api.rest-cfcs`).
|
||||
|
||||
#### reloadKey
|
||||
|
||||
**Available in:** Taffy 1.2+<br/>
|
||||
@@ -497,6 +584,13 @@ To provide a simulated response, add an additional method to your Resource CFCs
|
||||
**Default:** False<br/>
|
||||
**Description:** Whether or not Taffy will display user friendly documentation when the dashboard is disabled.
|
||||
|
||||
#### allowGoogleFonts
|
||||
|
||||
**Available in:** Taffy 4.0+<br/>
|
||||
**Type:** Boolean<br/>
|
||||
**Default:** True<br/>
|
||||
**Description:** When true, the dashboard and documentation pages load the [Atkinson Hyperlegible](https://fonts.google.com/specimen/Atkinson+Hyperlegible) and [Atkinson Hyperlegible Mono](https://fonts.google.com/specimen/Atkinson+Hyperlegible+Mono) fonts from Google Fonts. Set to false to prevent any external requests to Google, in which case the dashboard falls back to system fonts.
|
||||
|
||||
#### docs.APIName
|
||||
|
||||
**Available in:** Taffy 3.0+<br/>
|
||||
@@ -570,11 +664,32 @@ The allowed verbs, of course, are the ones allowed by the requested resource, as
|
||||
|
||||
In addition, as of Taffy 3.1.0, you can set this setting to a string of allowable hosts, as a (comma, semicolon, or space) delimited list:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
variables.framework.allowCrossDomain =
|
||||
"http://example.com; http://foo.bar, http://google.com";
|
||||
```
|
||||
|
||||
#### exposeTaffyHeaders
|
||||
|
||||
**Available in:** Taffy 3.8+<br/>
|
||||
**Type:** Boolean<br/>
|
||||
**Default:** true<br/>
|
||||
**Description:** Determines if the standard Taffy debug HTTP response headers should be included with each request. The Taffy debug headers are:
|
||||
|
||||
- `X-TAFFY-RELOADED` — Determines if the Taffy configuration was reloaded on the request.
|
||||
- `X-TIME-TO-RELOAD` — The time it took for Taffy to initialize.
|
||||
- `X-TIME-IN-PARSE` — The time it took to parse the request.
|
||||
- `X-TIME-IN-ONTAFFYREQUEST` — The time spent in the `onTaffyRequest` method.
|
||||
- `X-TIME-IN-RESOURCE` — The time spent executing the requested resource.
|
||||
- `X-TIME-IN-CACHE-CHECK` — The time spent checking for a cached response.
|
||||
- `X-TIME-IN-CACHE-GET` — The time spent to retrieve a cached response.
|
||||
- `X-TIME-IN-CACHE-SAVE` — The time spent to save a cached response.
|
||||
- `X-TIME-IN-SERIALIZE` — The time spent serializing the response.
|
||||
- `X-TIME-IN-TAFFY` — The time spent executing the Taffy internals.
|
||||
- `X-TIME-IN-ONTAFFYREQUESTEND` — The time spent in the `onTaffyRequestEnd` method.
|
||||
|
||||
Setting this to `false` will prevent these response headers from being written to the HTTP stream.
|
||||
|
||||
#### globalHeaders
|
||||
|
||||
**Available in:** Taffy 1.2+<br/>
|
||||
@@ -611,15 +726,15 @@ Global headers are static. You set them on application initialization and they d
|
||||
|
||||
**Available in:** Taffy 1.2+<br/>
|
||||
**Type:** Boolean<br/>
|
||||
**Default:** true<br/>
|
||||
**Description:** When an error occurs that is not otherwise handled, this option tells Taffy to attempt to format the error information as JSON and return that (regardless of the requested return format). As of Taffy 2.1 this also includes a structured stack trace with file names and line numbers.
|
||||
**Default:** false<br/>
|
||||
**Description:** When an error occurs that is not otherwise handled, this option tells Taffy to attempt to format the error information as JSON and return that (regardless of the requested return format). As of Taffy 2.1 this also includes a structured stack trace with file names and line numbers. Default changed to `false` in Taffy 4.x to prevent accidental stack trace disclosure in production.
|
||||
|
||||
#### exceptionLogAdapter
|
||||
|
||||
**Available in:** Taffy 1.2+<br/>
|
||||
**Type:** String<br/>
|
||||
**Default:** "taffy.bonus.LogToEmail"<br/>
|
||||
**Description:** CFC dot-notation path to the exception logging adapter you want to use. Default adapter simply emails all exceptions. See [Exception Logging Adapters](https://github.com/atuttle/Taffy/wiki/Exception-Logging-Adapters) for more details.
|
||||
**Default:** "taffy.bonus.LogToDevNull"<br/>
|
||||
**Description:** CFC dot-notation path to the exception logging adapter you want to use. Default adapter discards all exceptions silently. See [Exception Logging Adapters](https://github.com/atuttle/Taffy/wiki/Exception-Logging-Adapters) for more details.
|
||||
|
||||
#### exceptionLogAdapterConfig
|
||||
|
||||
@@ -637,7 +752,7 @@ Global headers are static. You set them on application initialization and they d
|
||||
|
||||
**NOTE FOR EXTERNAL BEAN FACTORY USERS (e.g. Coldspring, DI/1 etc)** If your external bean factory is initialized in onApplicationStart then you need to set the variables.framework.beanFactory after your bean factory has initialized, for example:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
component extends="taffy.core.api"
|
||||
{
|
||||
this.name = 'myapi';
|
||||
@@ -652,6 +767,28 @@ component extends="taffy.core.api"
|
||||
}
|
||||
```
|
||||
|
||||
#### openapi
|
||||
|
||||
**Available in:** Taffy 4.0+<br/>
|
||||
**Type:** Structure<br/>
|
||||
**Default:** `{ enabled: true }`<br/>
|
||||
**Description:** Controls the OpenAPI 3.1 spec endpoint served at `?openapi` / `?swagger`. Set `enabled` to `false` to disable the endpoint entirely (returns 403). Optional keys `description`, `contact`, and `license` are passed through to the spec's `info` block. `servers` (array of `{ url, description }` objects) overrides the auto-derived server URL.
|
||||
|
||||
```cfscript
|
||||
variables.framework.openapi = {
|
||||
enabled = true,
|
||||
description = "Public API for the Foo platform.",
|
||||
contact = { name = "API Team", email = "api@example.com" },
|
||||
license = { name = "MIT", url = "https://opensource.org/licenses/MIT" },
|
||||
servers = [
|
||||
{ url = "https://api.example.com", description = "Production" },
|
||||
{ url = "https://staging.api.example.com", description = "Staging" }
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
See the [OpenAPI / Swagger](#openapi--swagger) section for details on what gets generated.
|
||||
|
||||
#### environments
|
||||
|
||||
**Available in:** Taffy 1.3+<br/>
|
||||
@@ -710,7 +847,7 @@ Taffy calls this method during initialization to determine in which configured e
|
||||
|
||||
The returned value will be used to load environment-specific configuration. For example, if you have the following code in your Application.cfc, then the dashboard will be disabled in production:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
variables.framework = {
|
||||
|
||||
disableDashboard = false
|
||||
@@ -769,13 +906,13 @@ This method is optional, and allows you to inspect and potentially abort an API
|
||||
|
||||
If you do not return TRUE, allowing the request to continue as normal, then Taffy expects you to call and return the result of either **[noData()](#nodata)** or **[representationOf()](#representationof)**. If you simply want to return with a status code of 403 (which indicates "Not Allowed") and no response body, you could do this:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return noData().withStatus(403);
|
||||
```
|
||||
|
||||
Alternately, you could return some data to indicate that they owe you money or something:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return representationOf({
|
||||
error="Your account is past due. Please email accounts payable."
|
||||
})
|
||||
@@ -786,7 +923,7 @@ The options here are limited only by your imagination.
|
||||
|
||||
You can add data to the **requestArguments** structure and this will be passed on to any resource that handles the request. Simply add a key to the structure:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
function onTaffyRequest(
|
||||
verb,
|
||||
cfc,
|
||||
@@ -803,7 +940,7 @@ function onTaffyRequest(
|
||||
|
||||
In your resource:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
function get(myData) {
|
||||
//arguments.myData => "myValue"
|
||||
}
|
||||
@@ -811,13 +948,13 @@ function get(myData) {
|
||||
|
||||
You can use the method metadata for anything you see fit; but the original use case was for role-based security. Consider the following resource method:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
public function getData( id ) taffy_method="get" role="datareader" { ... }
|
||||
```
|
||||
|
||||
Taffy doesn't do anything with the **role** metadata on this method other than expose it to you in onTaffyRequest. So let's use the user's API key to find out what roles they have, and verify that the method's required role is among them. This is a snippet from your Application.cfc:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
function onTaffyRequest(verb, cfc, requestArgs, mime, head, methodMetadata){
|
||||
local.user = (...); //get user from api key...
|
||||
|
||||
@@ -914,7 +1051,7 @@ This method saves data in a way that makes it available to [exception log adapte
|
||||
|
||||
This is a convenience method used to make sure that certain all-numeric inputs get serialized as a string in the output not converted to numeric output. Examples are postal codes or phone numbers.
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return rep(
|
||||
queryToArray(myQuery, function (row) {
|
||||
row.phone = encode.string(row.phone);
|
||||
@@ -938,7 +1075,7 @@ Behaves like `noData()` except that it sets the status code to 204 and the Conte
|
||||
|
||||
This method allows you to specify that there is no data to be returned for the current request. Generally, you would use it in conjunction with the **withStatus** method to set a specific return status for the request. For example, if the requested resource doesn't exist, you could return a 404 error like so:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return noData().withStatus(404);
|
||||
```
|
||||
|
||||
@@ -956,7 +1093,7 @@ This method transforms a ColdFusion query object into an array of structures. It
|
||||
|
||||
The callback function can be used to efficiently transform keys in the structure before it is added to the array without additional looping. For example, you can use it to format dates in a particular style. **Your callback must return a value.**
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
queryToArray(someQ, function (row) {
|
||||
row.startDate = dateFormat(row.startDate, "yyyy-mm-dd");
|
||||
return row;
|
||||
@@ -965,7 +1102,7 @@ queryToArray(someQ, function (row) {
|
||||
|
||||
When you want to return the resulting array as your API response, you must still wrap it in a [representationOf](#rep-1) call:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return rep(queryToArray(someQ));
|
||||
```
|
||||
|
||||
@@ -983,7 +1120,7 @@ This method transforms a ColdFusion query object into a structure. If there is m
|
||||
|
||||
The callback function is passed the column name and the value, and can be used to efficiently transform keys in the structure as they are read from the query without need for additional looping. For example, you can use it to format dates in a particular style. **Your callback must return a value.**
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return queryToStruct(someQ, function (colName, val) {
|
||||
if (colName == "startDate") {
|
||||
return dateFormat(val, "yyyy-mm-dd");
|
||||
@@ -1020,7 +1157,7 @@ Data can be of any type, including complex data types like queries, structures,
|
||||
|
||||
What you pass to this method is simply handed off to the logging adapter. You may use one of the included adapters (LogToEmail, LogToBuglogHQ, LogToLog, or LogToHoth), or a custom logging adapter. If you write a custom logging adapter, it should implement the `taffy.bonus.ILogAdapter` interface.
|
||||
|
||||
If you don't configure a logging adapter, the default is LogToEmail, but the default `from` and `to` email addresses are not useful. See [Exception Log Adapters](https://github.com/atuttle/Taffy/wiki/Exception-Logging-Adapters) for more information on configuring logging adapters.
|
||||
If you don't configure a logging adapter, the default is LogToDevNull, which silently discards exceptions. See [Exception Log Adapters](https://github.com/atuttle/Taffy/wiki/Exception-Logging-Adapters) for more information on configuring logging adapters.
|
||||
|
||||
#### streamBinary()
|
||||
|
||||
@@ -1031,7 +1168,7 @@ If you don't configure a logging adapter, the default is LogToEmail, but the def
|
||||
|
||||
Use this method in place of `representationOf()` to return a stream of binary data. Useful for streaming things like dynamically generated PDFs. **Note: ** When streaming binary data as the response, you must set the mime type manually using [withMime()](#withmime). For example:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return streamBinary(local.pdf).withStatus(200).withMime("application/pdf");
|
||||
```
|
||||
|
||||
@@ -1044,7 +1181,7 @@ return streamBinary(local.pdf).withStatus(200).withMime("application/pdf");
|
||||
|
||||
Use this method in place of `representationOf()` to stream a file from disk (or VFS). Optionally append `.andDelete( true )` to delete the file once streaming is complete. **Note: ** When streaming binary data as the response, you must set the mime type manually using [withMime()](#withmime). For example:
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return streamFile("/foo.txt")
|
||||
.andDelete(true)
|
||||
.withStatus(200)
|
||||
@@ -1069,7 +1206,7 @@ Use this method in place of `representationOf()` to stream an image from disk (o
|
||||
|
||||
This special method _**requires**_ the use of either **noData** or **representationOf**. It adds custom headers to the return. Additional use of **withStatus** optional.
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return representationOf(myData).withHeaders({"X-POWERED-BY"="Taffy 2.0!"});
|
||||
```
|
||||
|
||||
@@ -1082,7 +1219,7 @@ return representationOf(myData).withHeaders({"X-POWERED-BY"="Taffy 2.0!"});
|
||||
|
||||
This special method _**requires**_ the use of either **streamFile** or **streamBinary**. It overrides the default mime type header for the return.
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return streamFile("kittens/cuteness.pdf").withMime("application/pdf");
|
||||
```
|
||||
|
||||
@@ -1098,7 +1235,7 @@ This special method _**requires**_ the use of either **noData** or **representat
|
||||
|
||||
_If you do not specify a return status code, Taffy will always return status code 200 (OK) by default._
|
||||
|
||||
```js
|
||||
```cfscript
|
||||
return noData().withStatus(404, "Not Found");
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user