How to use isPreflightRequest method in Cypress

Best JavaScript code snippet using cypress

HTTPRequestProcessor.js

Source:HTTPRequestProcessor.js Github

copy

Full Screen

1'use strict';2// Including native modules.3const filesystem = require('fs');4const queryString = require('querystring');5// Including Lala's modules.6const RequestProcessor = require('../RequestProcessor');7const UploadedFile = require('../../../Types/UploadedFile');8const HelperRepository = require('../../../Helpers/HelperRepository');9const {10    InvalidArgumentException11} = require('../../../Exceptions');12/**13 * @typedef {RequestProcessorConfiguration} HTTPRequestProcessorConfiguration An object containing all the properties supported by this class.14 *15 * @property {boolean} [allowMethodOverride=false] If set to "true" request method can be defined setting a proper parameter as part of the request.16 * @property {string} [methodOverrideParamName="_method"] The name of the GET/POST parameter that contains the name of the method that will be used in method override (if enabled).17 */18/**19 * Allows to handle client requests processing data and parameters sent over the HTTP protocol.20 */21class HTTPRequestProcessor extends RequestProcessor {22    /**23     * Extract the eTags contained in a given header.24     *25     * @param {string} headerValue A string representing the header contents.26     *27     * @returns {string[]} An array of strings containing the eTags found.28     *29     * @protected30     */31    static _extractETags(headerValue){32        const extractedETags = [];33        // Extract the eTags from the given header contents.34        const eTags = headerValue.split(','), length = eTags.length;35        // Clean up every eTag.36        for ( let i = 0 ; i < length ; i++ ){37            // Remove trailing spaces.38            eTags[i] = eTags[i].trim();39            if ( eTags[i][0] === 'W' && eTags[i][1] === '/' ){40                // Remove the "W/" prefix (indicating that this is a "weak" eTag).41                eTags[i] = eTags[i].substr(2);42            }43            // Remove quotes.44            eTags[i] = eTags[i].substr(1, eTags[i].length - 2);45            extractedETags.push(eTags[i]);46        }47        return extractedETags;48    }49    /**50     * Returns all the properties supported by this class and their default values.51     *52     * @returns {HTTPRequestProcessorConfiguration} An object containing as key the property name and as value its default value.53     *54     * @override55     */56    static getDefaultConfiguration(){57        const baseConfiguration = RequestProcessor.getDefaultConfiguration();58        baseConfiguration.allowMethodOverride = false;59        baseConfiguration.methodOverrideParamName = '_method';60        return baseConfiguration;61    }62    /**63     * Adds the GET parameters extracted and parsed from the query string.64     *65     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.66     *67     * @protected68     */69    _addQueryParameters(request){70        // Processing GET parameters.71        request.query = request._queryStartIndex === -1 ? Object.create(null) : queryString.parse(request.url.substr(request._queryStartIndex + 1));72    }73    /**74     * Adds user credentials found by processing the request URL and the HTTP headers.75     *76     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.77     *78     * @protected79     */80    _addCredentials(request){81        request.credentials = request.authMethod = null;82        if ( request.headers.authorization !== '' && typeof request.headers.authorization === 'string' ){83            // Separate credentials from the authentication method.84            const components = request.headers.authorization.split(' ', 2);85            if ( components.length === 2 ){86                request.authMethod = components[0].toLowerCase();87                if ( request.authMethod === 'basic' ){88                    // Decode user credentials used in basic HTTP authentication mechanism.89                    const credentials = Buffer.from(components[1], 'base64').toString().split(':');90                    if ( credentials.length === 2 ){91                        request.credentials = {92                            username: credentials[0],93                            password: credentials[1]94                        };95                    }96                }97            }98        }99    }100    /**101     * Adds the client provided language codes to the request object given.102     *103     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.104     *105     * @protected106     */107    _addAcceptedLanguages(request){108        request.languages = Object.create(null);109        request.preferredLanguage = request.preferredLanguageScore = null;110        if ( request.headers['accept-language'] !== '' && typeof request.headers['accept-language'] === 'string' ){111            const blocks = request.headers['accept-language'].split(','), length = blocks.length;112            for ( let i = 0 ; i < length ; i++ ){113                // Split the language code and its score.114                const block = blocks[i].split(';');115                const languageCode = block[0].trim();116                if ( block.length === 1 ){117                    // No score found, current language is the default one, set score to 1 (the maximum value allowed).118                    request.languages[languageCode] = 1;119                    if ( request.preferredLanguage === null ){120                        request.preferredLanguage = languageCode;121                        request.preferredLanguageScore = 1;122                    }123                }else if ( block[1].indexOf('q=') === 0 ){124                    // Process priority value defined for current language.125                    const priority = parseFloat(block[1].substr(2));126                    if ( !isNaN(priority) && priority <= 1 ){127                        request.languages[languageCode] = priority;128                        if ( request.preferredLanguage === null ){129                            request.preferredLanguage = languageCode;130                            request.preferredLanguageScore = priority;131                        }132                    }133                }134            }135        }136    }137    /**138     * Extract segments from request URL's path and then add them to the request object given.139     *140     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.141     *142     * @protected143     */144    _addURLSegments(request){145        if ( request._queryStartIndex === -1 ){146            request.segments = request.url.substr(1).split('/');147        }else{148            request.segments = request.url.substr(0, request._queryStartIndex).split('/');149        }150    }151    /**152     * Applies method override, if enabled, setting current request according to client provided overriding parameter or header.153     *154     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.155     *156     * @protected157     */158    _processMethodOverride(request){159        request.originalMethod = request.method;160        request.methodOverrideParamName = null;161        request.methodOverridden = false;162        if ( this._allowMethodOverride === true ){163            // Method override enabled, save the name of the parameter that should contains the method name making it available across processors.164            request.methodOverrideParamName = this._methodOverrideParamName;165            if ( request.query[this._methodOverrideParamName] !== '' && typeof request.query[this._methodOverrideParamName] === 'string' ){166                // New method name found in a GET parameter.167                request.method = request.query[this._methodOverrideParamName].toUpperCase();168                request.methodOverridden = true;169            }else if ( request.headers['x-http-method-override'] !== '' && typeof request.headers['x-http-method-override'] === 'string' ){170                // New method name found from the "X-Http-Method-Override" HTTP header.171                request.method = request.headers['x-http-method-override'].toUpperCase();172                request.methodOverridden = true;173            }174        }175    }176    /**177     * Parses the content of the "Range" header involved in HTTP range request (used, for instance, in video streaming).178     *179     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.180     *181     * @protected182     */183    _addRange(request){184        request.ranges = [];185        if ( request.headers.range !== '' && typeof request.headers.range === 'string' && request.headers.range.indexOf('bytes=') === 0 ){186            // Extract the header content without the "bytes=" indicating the measurement unit, note that "bytes" is the only supported unit.187            const ranges = request.headers.range.substr(6).split(','), length = ranges.length;188            // Process each requested range.189            for ( let i = 0 ; i < length ; i++ ){190                // Clean up the range syntax.191                ranges[i] = ranges[i].trim();192                const index = ranges[i].indexOf('-');193                if ( index >= 0 ){194                    let rangeStart = null, rangeEnd = null, suffixLength = null;195                    if ( index === 0 ){196                        // This value indicated the number of bytes at the end of the file to return.197                        suffixLength = parseInt(ranges[i].substr(1));198                    }else{199                        // Extract the number of bytes the returned slice should start from.200                        rangeStart = parseInt(ranges[i].substr(0, index));201                        // If the "-" is not at the end of the string extract the end index as well.202                        rangeEnd = index === ( ranges[i].length - 1 ) ? null : parseInt(ranges[i].substr(index + 1));203                    }204                    request.ranges.push({205                        rangeStart: rangeStart,206                        rangeEnd: rangeEnd,207                        suffixLength: suffixLength208                    });209                }210            }211        }212    }213    /**214     * Extracts all the pieces of information from the conditional HTTP headers and the add the conditionals parameters to the request object.215     *216     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.217     *218     * @protected219     */220    _addConditionals(request){221        request.conditionals = {222            matchAnyETag: false,223            matchETags: [],224            modifiedSince: null,225            mismatchAnyETag: false,226            mismatchETags: [],227            unmodifiedSince: null,228            vary: [],229            varyAny: false230        };231        if ( request.headers['if-match'] !== '' && typeof request.headers['if-match'] === 'string' ){232            if ( request.headers['if-match'] === '*' ){233                request.conditionals.matchAnyETag = true;234            }else{235                // Extract the list of eTags.236                request.conditionals.matchETags = HTTPRequestProcessor._extractETags(request.headers['if-match']);237            }238        }239        if ( request.headers['if-modified-since'] !== '' && typeof request.headers['if-modified-since'] === 'string' ){240            const timestamp = Date.parse(request.headers['if-modified-since']);241            if ( !isNaN(timestamp) ){242                request.conditionals.modifiedSince = new Date(timestamp);243            }244        }245        if ( request.headers['if-none-match'] !== '' && typeof request.headers['if-none-match'] === 'string' ){246            if ( request.headers['if-none-match'] === '*' ){247                request.conditionals.mismatchAnyETag = true;248            }else{249                // Extract the list of eTags.250                request.conditionals.mismatchETags = HTTPRequestProcessor._extractETags(request.headers['if-none-match']);251            }252        }253        if ( request.headers['if-unmodified-since'] !== '' && typeof request.headers['if-unmodified-since'] === 'string' ){254            const timestamp = Date.parse(request.headers['if-unmodified-since']);255            if ( !isNaN(timestamp) ){256                request.conditionals.unmodifiedSince = new Date(timestamp);257            }258        }259        if ( request.headers['vary'] !== '' && typeof request.headers['vary'] === 'string' ){260            if ( request.headers['vary'] === '*' ){261                request.conditionals.varyAny = true;262            }else{263                // Extract the list of HTTP headers.264                const headers = request.headers['vary'].split(','), length = headers.length;265                // Clean up and normalize each header of the list.266                for ( let i = 0 ; i < length ; i++ ){267                    request.conditionals.vary.push(headers[i].trim().toLowerCase());268                }269            }270        }271    }272    /**273     * Extracts the MIME types accepted and then declared by the client side as part of the "Accept" HTTP header.274     *275     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.276     *277     * @protected278     */279    _addAccept(request){280        request.accept = Object.create(null);281        if ( request.headers.accept !== '' && typeof request.headers.accept === 'string' ){282            // Split the MIME type list into an array of strings.283            const mimes = request.headers.accept.split(','), length = mimes.length;284            for ( let i = 0 ; i < length ; i++ ){285                // Clean up current MIME type.286                mimes[i] = mimes[i].trim();287                // Extract the preference score associated to the MIME type.288                const index = mimes[i].indexOf(';');289                let mime, score;290                if ( index === -1 ){291                    // No score associated, use 1.292                    mime = mimes[i];293                    score = 1;294                }else{295                    // Extract and cast the score associated, if not valid, use 1 instead.296                    mime = mimes[i].substr(0, index);297                    score = parseFloat(mimes[i].substr(index));298                    if ( isNaN(score) ){299                        score = 1;300                    }301                }302                if ( mime !== '' ){303                    request.accept[mime] = score;304                }305            }306        }307    }308    /**309     * The class constructor.310     *311     * @param {?HTTPRequestProcessorConfiguration} [configuration=null] An object containing the values for class properties.312     */313    constructor(configuration = null){314        super(configuration);315        /**316         * @type {boolean} [_allowMethodOverride=false] If set to "true" request method can be defined setting a proper parameter as part of the request.317         *318         * @protected319         */320        this._allowMethodOverride = false;321        /**322         * @type {string} [_methodOverrideParamName="_method"] The name of the GET/POST parameter that contains the name of the method that will be used in method override (if enabled).323         *324         * @protected325         */326        this._methodOverrideParamName = '_method';327        if ( configuration !== null && typeof configuration === 'object' ){328            // Setup internal properties.329            this.configure(configuration);330        }331    }332    /**333     * Configures internal properties based on the configuration object given, this method is chainable.334     *335     * @param {HTTPRequestProcessorConfiguration} configuration An object containing the values for class properties.336     *337     * @returns {HTTPRequestProcessor}338     *339     * @throws {InvalidArgumentException} If an invalid configuration object is given.340     *341     * @override342     */343    configure(configuration){344        super.configure(configuration);345        if ( configuration.hasOwnProperty('allowMethodOverride') && typeof configuration.allowMethodOverride === 'boolean' ){346            this._allowMethodOverride = configuration.allowMethodOverride;347        }348        if ( configuration.hasOwnProperty('methodOverrideParamName') && configuration.methodOverrideParamName !== '' && typeof configuration.methodOverrideParamName === 'string' ){349            this._methodOverrideParamName = configuration.methodOverrideParamName;350        }351        return this;352    }353    /**354     * Adds basic properties to a given HTTP request object, for instance GET parameters, user credentials and user languages.355     *356     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.357     * @param {module:http.ServerResponse} response An instance of the built-in class "ServerResponse" representing the response that will be sent back to the client.358     *359     * @returns {Promise<void>}360     *361     * @async362     */363    async process(request, response){364        await super.process(request, response);365        request.user = request.authenticator = request.userSession = request.cookies = request.preflightRequestMethod = null;366        // Marks those properties that will be used in request body processing.367        request.rawBody = undefined;368        request.params = Object.create(null);369        request.secure = request.connection.hasOwnProperty('encrypted');370        request.ignoreConditionalsHeaders = request.isPreflightRequest = false;371        if ( request.method === 'OPTIONS' && typeof request.headers.origin === 'string' && request.headers.origin !== '' ){372            if ( request.headers['access-control-request-method'] !== '' && typeof request.headers['access-control-request-method'] === 'string' ){373                request.isPreflightRequest = true;374                request.preflightRequestMethod = request.headers['access-control-request-method'];375            }376        }377        request.doNotTrack = request.headers['dnt'] === '1';378        this._addQueryParameters(request);379        // Apply method override (if enabled).380        this._processMethodOverride(request);381        this._addCredentials(request);382        this._addAcceptedLanguages(request);383        this._addURLSegments(request);384        this._addRange(request);385        this._addConditionals(request);386        this._addAccept(request);387        // Add helper functions.388        HelperRepository.inject(request, 'com.lala.server.processor.HTTPRequestProcessor.request', {389            context: {390                request: request,391                response: response392            }393        });394        HelperRepository.inject(response, 'com.lala.server.processor.HTTPRequestProcessor.response', {395            context: {396                request: request,397                response: response398            }399        });400    }401    /**402     * Destroys all temporary data that is not more required to exist.403     *404     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.405     *406     * @return {Promise<void>}407     *408     * @protected409     */410     async killRequest(request){411        if ( request.hasOwnProperty('files') && request.files !== null && typeof request.files === 'object' ){412            setImmediate(async () => {413                const processes = [];414                // Remove all the uploaded files from their temporary location.415                for ( const name in request.files ){416                    if ( request.files[name] instanceof UploadedFile && !request.files[name].moved() ){417                        // Remove the file only if it has not been moved to a permanent location.418                        processes.push(filesystem.promises.unlink(request.files[name].getPath()));419                    }420                }421                await Promise.all(processes);422            });423        }424    }425}...

Full Screen

Full Screen

CORSOptions.js

Source:CORSOptions.js Github

copy

Full Screen

1'use strict';2// Including Lala's modules.3const {4    InvalidArgumentException5} = require('../../Exceptions');6/**7 * @callback allowOriginCallback The callback that allows to set the allowed origin dynamically.8 *9 * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.10 * @param {module:http.ServerResponse} response An instance of the built-in class "ServerResponse" representing the response that will be sent back to the client.11 *12 * @returns {?string} A string containing the allowed origin or null if any origin should be allowed.13 */14/**15 * Allows to configure the Cross-Origin Resource Sharing (CORS) mechanism on a route, router or server.16 */17class CORSOptions {18    /**19     * Returns the origin to declare to the client as the allowed one.20     *21     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.22     * @param {module:http.ServerResponse} response An instance of the built-in class "ServerResponse" representing the response that will be sent back to the client.23     *24     * @returns {?string} A string containing the origin to declare, if any origin should be allowed will be returned null.25     *26     * @protected27     */28    _getComputedOrigin(request, response){29        let origin = this._allowOrigin;30        if ( typeof this._allowOriginCallback === 'function' ){31            // A callback has been defined, generate the origin dynamically.32            origin = this._allowOriginCallback(request, response);33        }34        return origin;35    }36    /**37     * Checks if a request is valid according to defined CORS settings.38     *39     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.40     * @param {string} origin The origin where the request comes from.41     *42     * @returns {boolean} If the request is valid will be returned "true".43     *44     * @protected45     */46    _validateRequest(request, origin){47        let valid = false;48        // Check if the given origin is accepted.49        if ( origin === '*' || request.headers.origin === origin ){50            const requestMethod = request.headers['access-control-request-method'];51            // Check if the method of the request the client is intended to do is accepted.52            if ( this._allowMethods === null || this._allowMethods.indexOf(requestMethod) >= 0 ){53                if ( this._allowHeaders === null ){54                    // Any HTTP header is accepted.55                    valid = true;56                }else{57                    // Check if every declared HTTP header is accepted.58                    const requestHeaders = request.headers['access-control-request-headers'].split(',');59                    const length = requestHeaders.length;60                    let found = true, i = 0;61                    while ( i < length && found ){62                        if ( this._allowHeaders.indexOf(requestHeaders[i].trim().toLowerCase()) === -1 ){63                            found = false;64                        }65                        i++;66                    }67                    valid = found;68                }69            }70        }71        return valid;72    }73    /**74     * The class constructor.75     */76    constructor() {77        /**78         * @type {?string} [_allowOrigin] A string containing the origin URL where requests are allowed from, if null, any URL will be accepted.79         *80         * @protected81         */82        this._allowOrigin = null;83        /**84         * @type {?allowOriginCallback} [_allowOriginCallback] A callback function to invoke in order to get the origin URL dynamically.85         *86         * @protected87         */88        this._allowOriginCallback = null;89        /**90         * @type {?string[]} [_exposeHeaders=[]] An array of strings containing all the HTTP headers that can be exposed as part of the response, if null, any header will be exposed.91         *92         * @protected93         */94        this._exposeHeaders = [];95        /**96         * @type {number} [_maxAge=0] An integer number greater than zero representing how long CORS directives should be cached for on the client side, if zero it will be ignored.97         *98         * @protected99         */100        this._maxAge = 0;101        /**102         * @type {boolean} [_allowCredentials=false] If set to "true" credentials (cookies, authorization headers or TLS client certificates) can be exposed to front-end.103         *104         * @protected105         */106        this._allowCredentials = false;107        /**108         * @type {?string[]} [_allowMethods] An array of strings containing the allowed HTTP methods, if null, any method is allowed.109         *110         * @protected111         */112        this._allowMethods = null;113        /**114         * @type {?string[]} [_allowHeaders] An array of strings containing the allowed HTTP headers, if null, any header is allowed.115         *116         * @protected117         */118        this._allowHeaders = null;119        /**120         * @type {boolean} [_strict=false] If set to "true" incoming requests will be actively validated according to defined settings, if invalid, they will be blocked.121         *122         * @protected123         */124        this._strict = false;125    }126    /**127     * Sets the origin the requests are allowed to come from, this method is chainable.128     *129     * @param {?string} allowOrigin A string containing the origin or null if any origin is accepted.130     *131     * @returns {CORSOptions}132     *133     * @throws {InvalidArgumentException} If an invalid origin is given.134     */135    setAllowOrigin(allowOrigin){136        if ( allowOrigin !== null && ( allowOrigin === '' || typeof allowOrigin !== 'string' ) ){137            throw new InvalidArgumentException('Invalid allowed origin.', 1);138        }139        this._allowOrigin = allowOrigin;140        return this;141    }142    /**143     * Return the origin the requests are allowed to come from that has been defined.144     *145     * @returns {?string} A string containing the origin or null if any origin is accepted.146     */147    getAllowOrigin(){148        return this._allowOrigin;149    }150    /**151     * Sets a callback function that will be invoked in order to determinate the allowed origin for a given request, this method is chainable.152     *153     * @param {?allowOriginCallback} allowOriginCallback A callback function to invoke or null if the allowed origin should be static.154     *155     * @returns {CORSOptions}156     *157     * @throws {InvalidArgumentException} If an invalid callback function is given.158     */159    setAllowOriginCallback(allowOriginCallback){160        if ( allowOriginCallback !== null && typeof allowOriginCallback !== 'function' ){161            throw new InvalidArgumentException('Invalid callback function.', 1);162        }163        this._allowOriginCallback = allowOriginCallback;164        return this;165    }166    /**167     * Returns the callback function that has been defined in order to determinate the allowed origin dynamically.168     *169     * @returns {?allowOriginCallback} The callback function or null if none has been defined.170     */171    getAllowOriginCallback(){172        return this._allowOriginCallback;173    }174    /**175     * Sets the HTTP headers that can be exposed as part of the response, this method is chainable.176     *177     * @param {?string[]} exposeHeaders An array of strings containing the headers, if set to null, any header will be exposed.178     *179     * @returns {CORSOptions}180     *181     * @throws {InvalidArgumentException} If an invalid array of headers is given.182     */183    setExposeHeaders(exposeHeaders){184        if ( exposeHeaders !== null || !Array.isArray(exposeHeaders) ){185            throw new InvalidArgumentException('Invalid exposed headers list.', 1);186        }187        if ( exposeHeaders === null ){188            this._exposeHeaders = null;189        }else{190            // Normalize the given headers converting the into the lower case form.191            this._exposeHeaders = [];192            const length = exposeHeaders.length;193            for ( let i = 0 ; i < length ; i++ ){194                this._exposeHeaders.push(exposeHeaders[i].toLowerCase());195            }196        }197        return this;198    }199    /**200     * Returns the HTTP headers that can be exposed as part of the response that have been defined.201     *202     * @returns {?string[]} An array of strings containing the headers or null if none has been defined.203     */204    getExposeHeaders(){205        return this._exposeHeaders;206    }207    /**208     * Sets how long CORS directives should be cached for on the client side, this method is chainable.209     *210     * @param {number} maxAge An integer number greater or equal than zero representing the how long cache should last in seconds, if zero no caching will be applied.211     *212     * @returns {CORSOptions}213     *214     * @throws {InvalidArgumentException} If an invalid max age value is given.215     */216    setMaxAge(maxAge){217        if ( maxAge === null || isNaN(maxAge) || maxAge < 0 ){218            throw new InvalidArgumentException('Invalid max age value.', 1);219        }220        this._maxAge = maxAge;221        return this;222    }223    /**224     * Returns how long CORS directives should be cached for on the client side.225     *226     * @returns {number} An integer number greater or equal than zero representing the how long cache should last in seconds or zero if no caching should be applied.227     */228    getMaxAge(){229        return this._maxAge;230    }231    /**232     * Sets if credentials (cookies, authorization headers or TLS client certificates) can be exposed to front-end, this method is chainable.233     *234     * @param {boolean} allowCredentials If set to "true" credentials will be allowed to be exposed to the front-end.235     *236     * @returns {CORSOptions}237     */238    setAllowCredentials(allowCredentials){239        this._allowCredentials = allowCredentials === true;240        return this;241    }242    /**243     * Returns if credentials (cookies, authorization headers or TLS client certificates) can be exposed to front-end.244     *245     * @returns {boolean} If credentials are allowed to be exposed to the front-end will be returned "true".246     */247    getAllowCredentials(){248        return this._allowCredentials === true;249    }250    /**251     * Sets the allowed HTTP methods, this method is chainable.252     *253     * @param {?string[]} allowMethods An array of strings containing the HTTP methods accepted for the incoming requests, if null any method will be accepted.254     *255     * @returns {CORSOptions}256     *257     * @throws {InvalidArgumentException} If an invalid method list is given.258     */259    setAllowMethods(allowMethods){260        if ( allowMethods !== null && !Array.isArray(allowMethods) ){261            throw new InvalidArgumentException('Invalid allowed HTTP methods list.', 1);262        }263        if ( allowMethods === null ){264            this._allowMethods = null;265        }else{266            // Normalize the given methods converting the into the upper case form.267            this._allowMethods = [];268            const length = allowMethods.length;269            for ( let i = 0 ; i < length ; i++ ){270                this._allowMethods.push(allowMethods[i].toUpperCase());271            }272        }273        return this;274    }275    /**276     * Returns the list of allowed HTTP methods.277     *278     * @returns {?string[]} An array of strings containing the HTTP methods defined or null if any method is accepted.279     */280    getAllowMethods(){281        return this._allowMethods;282    }283    /**284     * Sets the HTTP headers that can be included in client requests, this method is chainable.285     *286     * @param {?string[]} allowHeaders An array containing the list of HTTP headers, if null any header will be accepted.287     *288     * @returns {CORSOptions}289     *290     * @throws {InvalidArgumentException} If an invalid header list is given.291     */292    setAllowHeaders(allowHeaders){293        if ( allowHeaders !== null && !Array.isArray(allowHeaders) ){294            throw new InvalidArgumentException('Invalid allowed HTTP headers list.', 1);295        }296        if ( allowHeaders === null ){297            this._allowHeaders = null;298        }else{299            // Normalize the given headers converting the into the lower case form.300            this._allowHeaders = [];301            const length = allowHeaders.length;302            for ( let i = 0 ; i < length ; i++ ){303                this._allowHeaders.push(allowHeaders[i].toLowerCase());304            }305        }306        return this;307    }308    /**309     * Returns the list of HTTP headers that can be included in client requests.310     *311     * @returns {?string[]} An array containing the list of HTTP headers or null if any header is accepted.312     */313    getAllowHeaders(){314        return this._allowHeaders;315    }316    /**317     * Sets if an active check must be performed on incoming requests in order to reject the ones that doesn't meet the defined CORS settings, this method is chainable.318     *319     * @param {boolean} strict If set to "true" an active check will be performed on incoming requests.320     *321     * @returns {CORSOptions}322     */323    setStrict(strict){324        this._strict = strict === true;325        return this;326    }327    /**328     * Returns if an active check should be performed on incoming requests.329     *330     * @returns {boolean} If an active check is going to be performed will be returned "true".331     */332    getStrict(){333        return this._strict === true;334    }335    /**336     * Generates the HTTP headers to include in the client response.337     *338     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.339     * @param {module:http.ServerResponse} response An instance of the built-in class "ServerResponse" representing the response that will be sent back to the client.340     *341     * @returns {Object.<string, string>} An object containing the generated headers as key/value pairs.342     */343    buildHeaders(request, response){344        const headers = {};345        // Get or generate the allowed origin to declare.346        const origin = this._getComputedOrigin(request, response);347        if ( request.isPreflightRequest !== true || this._validateRequest(request, origin) ){348            // Current request is valid according to defined CORS options, declare the CORS headers.349            headers['Access-Control-Allow-Origin'] = origin === null ? '*' : origin;350            if ( this._allowCredentials === true ){351                headers['Access-Control-Allow-Credentials'] = 'true';352            }353            if ( this._exposeHeaders === null ){354                headers['Access-Control-Expose-Headers'] = '*';355            }else if ( Array.isArray(this._exposeHeaders) && this._exposeHeaders.length > 0 ){356                headers['Access-Control-Expose-Headers'] = this._exposeHeaders.join(', ');357            }358            if ( request.isPreflightRequest === true ){359                // Current request is a valid OPTIONS request, declare the remaining CORS options providing the full CORS policy to the client.360                if ( this._maxAge > 0 ){361                    headers['Access-Control-Max-Age'] = this._maxAge;362                }363                if ( this._allowMethods === null ){364                    headers['Access-Control-Allow-Methods'] = '*';365                }else if ( Array.isArray(this._allowMethods) && this._allowMethods.length > 0 ){366                    headers['Access-Control-Allow-Methods'] = this._allowMethods.join(', ');367                }368                if ( this._allowHeaders === '*' ){369                    headers['Access-Control-Allow-Headers'] = '*';370                }else if ( Array.isArray(this._allowHeaders) && this._allowHeaders.length > 0 ){371                    headers['Access-Control-Allow-Headers'] = this._allowHeaders.join(', ');372                }373            }374        }375        return headers;376    }377    /**378     * Validates an incoming request according to defined CORS settings.379     *380     * @param {module:http.IncomingMessage} request An instance of the built-in class "IncomingMessage" containing all the connection properties.381     * @param {module:http.ServerResponse} response An instance of the built-in class "ServerResponse" representing the response that will be sent back to the client.382     *383     * @returns {boolean} If the given request meets the defined CORS settings will be returned "true".384     */385    validate(request, response){386        return this._strict !== true || this._validateRequest(request, this._getComputedOrigin(request, response));387    }388}...

Full Screen

Full Screen

implement-cors.js

Source:implement-cors.js Github

copy

Full Screen

...11			if (originMatches(origin, corsOptions)) {12				taskContext.origin = origin;13				if (isSimpleRequest(taskContext)) {14					handleSimpleResponse(taskContext, corsOptions);15				} else if (isPreflightRequest(taskContext)) {16					/*17					 * Stop the chain if we have created the response18					 */19					if (handlePreflightResponse(taskContext, corsOptions)) return true;20				} else {21					handleSimpleResponse(taskContext, corsOptions);22				}23			} else {24				console.warn(`Cross-origin request to ${taskContext.urlInfo.apiURL} with origin ${origin} does not match allowed origins ${corsOptions.AccessControlAllowOrigin}`);25			}26		}27	}28	return taskContext;29};...

Full Screen

Full Screen

route-matching.js

Source:route-matching.js Github

copy

Full Screen

...110    }111    return;112}113exports.getRouteForRequest = getRouteForRequest;114function isPreflightRequest(req) {115    return req.method === 'OPTIONS' && req.headers['access-control-request-method'];116}117/**118 * Is this a CORS preflight request that could be for an existing route?119 * If there is a matching route with method = 'OPTIONS', returns false.120 */121function matchesRoutePreflight(routes, req) {122    if (!isPreflightRequest(req)) {123        return false;124    }125    let hasCorsOverride = false;126    const matchingRoutes = lodash_1.default.filter(routes, ({ routeMatcher }) => {127        // omit headers from matching since preflight req will not send headers128        const preflightMatcher = lodash_1.default.omit(routeMatcher, 'method', 'headers', 'auth');129        if (!_doesRouteMatch(preflightMatcher, req)) {130            return false;131        }132        if (routeMatcher.method && /options/i.test(String(routeMatcher.method))) {133            hasCorsOverride = true;134        }135        return true;136    });...

Full Screen

Full Screen

cors-spec.js

Source:cors-spec.js Github

copy

Full Screen

...8                req.headers = {};9                req.headers.origin =  "abc.testy.com";10                req.headers['access-control-request-method'] = "PUT";11                req.method = "GET";12                assert.equal(cors.isPreflightRequest(req), false);13            });14            it('origin is not set', function () {15                var req = {};16                req.headers = {};17                req.headers['access-control-request-method'] = "PUT";18                req.method = "OPTIONS";19                assert.equal(cors.isPreflightRequest(req), false);20            });21            it('request method is not set', function () {22                var req = {};23                req.headers = {};24                req.headers.origin = "abc.testy.com";25                req.method = "OPTIONS";26                assert.equal(cors.isPreflightRequest(req), false);27            });28            it('origin is null string and referrer is trusted', function () {29                var req = {};30                req.headers = {};31                req.headers.origin = "null";32                req.method = "GET";33                req.headers.referer = "http://abc.testy.com/blah";34                assert.equal(cors.isPreflightRequest(req), false);35            });36        });37        describe('is in effect when', function(){38            it('cors preflight is detected', function () {39                var req = {};40                req.headers = {};41                req.headers.origin = "abc.testy.com";42                req.headers['access-control-request-method'] = "PUT";43                req.method = "OPTIONS";44                assert.equal(cors.isPreflightRequest(req), true);45            });46            it('origin is from an untrusted domain', function () {47                var req = {};48                req.headers = {};49                req.headers.origin = "abc.untrusted.com";50                req.method = "GET";51                assert.equal(cors.isOriginUntrusted(req), true);52            });53            it('origin is null string and referrer is untrusted', function () {54                var req = {};55                req.headers = {};56                req.headers.origin = 'null';57                req.method = "GET";58                req.headers.referer = "http://abc.untrusted.com/blah";...

Full Screen

Full Screen

Router.js

Source:Router.js Github

copy

Full Screen

...23        const pageController = PageController(repository, user);24        return await pageController.handle(requestHelper);25    };26    const getResponse = async () => {27        if (requestHelper.isPreflightRequest()) {28            return {};29        }30        const path = requestHelper.getPath();31        const row = routes.find(([key, value]) => {32            return key === path;33        });34        if (row) {35            const [path, callback] = row;36            if (typeof callback === "function") {37                return await callback();38            }39        }40        return getErrorResponse();41    };...

Full Screen

Full Screen

index.js

Source:index.js Github

copy

Full Screen

1require('dotenv').config();2const express = require('express');3const { getCategoriesRouter, getProductsRouter} = require('./productsOrCategoriesRoute.js');4const {handleLogInRoute, AUTH_TOKEN_HEADER_KEY} = require('./authentication.js');5const {sendErrorResponseToClient} = require('./helpers.js');6const {getEmailRouter} = require('./email.js');7const app = express();8app.use(express.json());9app.use(express.raw({type: "image/*", limit: "10mb"}));10function corsHandlerMiddleware(request, response, next){11    12    response.setHeader("Access-Control-Allow-Origin", "*");13    response.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");14    response.setHeader("Access-Control-Allow-Headers", `Content-Type, ${AUTH_TOKEN_HEADER_KEY}`);15    const isPreflightRequest = request.method === 'OPTIONS' && request.headers['origin'] && request.headers['access-control-request-method'];16    if (isPreflightRequest){17        response.end();18        return;19    }20    next();21}22app.use(corsHandlerMiddleware);23app.use('/login', handleLogInRoute);24app.use('/categories', getCategoriesRouter());25app.use('/products', getProductsRouter());26app.use('/email', getEmailRouter());27app.use((error, request, response, next) => {28    sendErrorResponseToClient(response, error);29});30const port = process.env.PORT || 5000;...

Full Screen

Full Screen

RequestHelper.js

Source:RequestHelper.js Github

copy

Full Screen

1const RequestHelper = req => {2    const getQueryData = () => {3        return req.query;4    };5    const isPostRequest = () => {6        return req.method === 'POST';7    };8    const isPreflightRequest = () => {9        return req.method === 'OPTIONS';10    };11    const getBodyData = async () => {12        if (isPostRequest() === false) {13            return null;14        }15        let chunks = [];16        await req.on('data', chunk => {17            chunks.push(chunk);18        });19        return Buffer.concat(chunks).toString();20    };21    const getJsonData = async () => {22        const body = await getBodyData();23        if (body) {24            return JSON.parse(body);25        }26        return null;27    };28    const getHeaders = () => {29        return req.headers;30    };31    const getHeader = key => {32        return req.headers[key] || null;33    };34    const getPath = () => {35        return req.path;36    };37    return {38        getQueryData,39        isPostRequest,40        isPreflightRequest,41        getBodyData,42        getJsonData,43        getHeaders,44        getHeader,45        getPath,46    }47};...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('Cypress.isPreflightRequest', () => {2  it('is a preflight request', () => {3      onBeforeLoad(win) {4        cy.stub(win, 'fetch').as('windowFetch')5      },6    })7    cy.get('#login').click()8    cy.get('@windowFetch').then((fetch) => {9      expect(Cypress.isPreflightRequest(fetch.getCall(0).args[0])).to.be.true10    })11  })12})13describe('Cypress.isPreflightRequest', () => {14  it('is a preflight request', () => {15      onBeforeLoad(win) {16        cy.stub(win, 'fetch').as('windowFetch')17      },18    })19    cy.get('#login').click()20    cy.get('@windowFetch').then((fetch) => {21      expect(Cypress.isPreflightRequest(fetch.getCall(0).args[0])).to.be.true22    })23  })24})25describe('Cypress.isPreflightRequest', () => {26  it('is a preflight request', () => {27      onBeforeLoad(win) {28        cy.stub(win, 'fetch').as('windowFetch')29      },30    })31    cy.get('#login').click()32    cy.get('@windowFetch').then((fetch) => {33      expect(Cypress.isPreflightRequest(fetch.getCall(0).args[0])).to.be.true34    })35  })36})37describe('Cypress.isPreflightRequest', () => {38  it('is a preflight request', () => {39      onBeforeLoad(win) {40        cy.stub(win, 'fetch').as('windowFetch')41      },42    })43    cy.get('#login').click()44    cy.get('@windowFetch').then((fetch) => {45      expect(Cypress.isPreflightRequest(fetch.getCall(0).args[0

Full Screen

Using AI Code Generation

copy

Full Screen

1Cypress.Commands.overwrite('request', (originalFn, ...options) => {2  if (isPreflightRequest(options)) {3    options = setPreflightHeaders(options);4  }5  return originalFn(...options);6});7function isPreflightRequest(options) {8  return options.method === 'POST' || options.method === 'PUT';9}10function setPreflightHeaders(options) {11  options.headers = {12  };13  options.method = 'OPTIONS';14  return options;15}

Full Screen

Using AI Code Generation

copy

Full Screen

1const isPreflightRequest = (request) => {2};3const isPreflightRequest = (request) => {4};5const isPreflightRequest = (request) => {6};7const isPreflightRequest = (request) => {8};9const isPreflightRequest = (request) => {10};11const isPreflightRequest = (request) => {12};13const isPreflightRequest = (request) => {14};15const isPreflightRequest = (request) => {16};17const isPreflightRequest = (request) => {18};19const isPreflightRequest = (request) => {20};21const isPreflightRequest = (request) => {22};23const isPreflightRequest = (request) => {24};25const isPreflightRequest = (

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('Cypress.isPreflightRequest', () => {2  it('should return false for non-preflight requests', () => {3    cy.server()4    cy.route('POST', '**/comments').as('postComment')5    cy.get('.network-post').click()6    cy.wait('@postComment').then((xhr) => {7      expect(xhr.response.body).to.have.property('name', 'Using POST in cy.route()')8      expect(Cypress.isPreflightRequest(xhr.request)).to.be.false9    })10  })11})12const getComments = () => {13    name: 'Using POST in cy.route()',14  })15}16const attachCommentsToDOM = (comments) => {17  return cy.get('.network-post-comment').append(comments)18}19const isPreflightRequest = (xhr) => {20}21$('.network-post').click(() => {22  getComments()23    .then((xhr) => {24      if (isPreflightRequest(xhr)) {25      }26      attachCommentsToDOM(xhr.response.body)27    })28})29const getComments = () => {30    name: 'Using POST in cy.route()',31  })32}33const attachCommentsToDOM = (comments) => {34  return cy.get('.network-post-comment').append(comments)35}36$('.network-post').click(() => {37  getComments()38    .then((xhr) => {39      if (Cypress.isPreflightRequest(xhr)) {40      }41      attachCommentsToDOM(xhr.response.body)42    })43})

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('Test', () => {2    it('Test', () => {3        cy.server()4        cy.route('POST', '/api/login').as('login')5        cy.get('[data-cy=username]').type('test')6        cy.get('[data-cy=password]').type('test')7        cy.get('[data-cy=login]').click()8        cy.wait('@login').then((xhr) => {9            expect(xhr.isPreflightRequest).to.equal(false)10        })11    })12})13{14    "reporterOptions": {},15}16module.exports = (on, config) => {17}18import './commands'19Cypress.Commands.add('login', (username, password) => {20    cy.visit('/login')21    cy.get('[data-cy=username]').type(username)22    cy.get('[data-cy=password]').type(password)23    cy.get('[data-cy=login]').click()24})25Cypress.Commands.add('drag', { prevSubject: 'element' }, (subject, options) => {26    cy.wrap(subject

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('Preflight request', () => {2  it('should check preflight request', () => {3    let isPreflightRequest = Cypress.isPreflightRequest;4      onBeforeLoad: (win) => {5        cy.stub(win, 'fetch').callsFake((...args) => {6          const [url, options] = args;7          if (isPreflightRequest(url, options)) {8            return Promise.resolve(new Response(null, { status: 204 }));9          }10          return window.fetch(...args);11        });12      }13    });14  });15});16describe('Preflight request', () => {17  it('should check preflight request', () => {18    cy.intercept('OPTIONS', '**', (req) => {19      req.reply();20    });21  });22});

Full Screen

Using AI Code Generation

copy

Full Screen

1it('test', () => {2    cy.server();3    cy.route('POST', '/users', 'fixture:users.json').as('createUser');4    cy.get('#form-first-name').type('Jane');5    cy.get('#form-last-name').type('Doe');6    cy.get('#form-submit').click();7    cy.wait('@createUser').its('request').should('be.preflightRequest');8});9.isPreflightRequest()10cy.route('POST', '/users', 'fixture:users.json').as('createUser');11cy.wait('@createUser').its('request').should('be.preflightRequest');

Full Screen

Using AI Code Generation

copy

Full Screen

1it('should only allow preflight requests', () => {2  cy.route({3    response: {}4  })5  cy.server()6  cy.get('button').click()7  cy.wait('@api')8  cy.get('@api').should(xhr => {9    expect(xhr.isPreflightRequest).to.be.true10  })11})

Full Screen

Cypress Tutorial

Cypress is a renowned Javascript-based open-source, easy-to-use end-to-end testing framework primarily used for testing web applications. Cypress is a relatively new player in the automation testing space and has been gaining much traction lately, as evidenced by the number of Forks (2.7K) and Stars (42.1K) for the project. LambdaTest’s Cypress Tutorial covers step-by-step guides that will help you learn from the basics till you run automation tests on LambdaTest.

Chapters:

  1. What is Cypress? -
  2. Why Cypress? - Learn why Cypress might be a good choice for testing your web applications.
  3. Features of Cypress Testing - Learn about features that make Cypress a powerful and flexible tool for testing web applications.
  4. Cypress Drawbacks - Although Cypress has many strengths, it has a few limitations that you should be aware of.
  5. Cypress Architecture - Learn more about Cypress architecture and how it is designed to be run directly in the browser, i.e., it does not have any additional servers.
  6. Browsers Supported by Cypress - Cypress is built on top of the Electron browser, supporting all modern web browsers. Learn browsers that support Cypress.
  7. Selenium vs Cypress: A Detailed Comparison - Compare and explore some key differences in terms of their design and features.
  8. Cypress Learning: Best Practices - Take a deep dive into some of the best practices you should use to avoid anti-patterns in your automation tests.
  9. How To Run Cypress Tests on LambdaTest? - Set up a LambdaTest account, and now you are all set to learn how to run Cypress tests.

Certification

You can elevate your expertise with end-to-end testing using the Cypress automation framework and stay one step ahead in your career by earning a Cypress certification. Check out our Cypress 101 Certification.

YouTube

Watch this 3 hours of complete tutorial to learn the basics of Cypress and various Cypress commands with the Cypress testing at LambdaTest.

Run Cypress automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful