import * as msRest from "@azure/ms-rest-js" ; import Operation from "../artifacts/operation" ; import Specifications from "../artifacts/specifications" ; import Context from "../Context" ; import UnsupportedRequestError from "../errors/UnsupportedRequestError" ; import IRequest from "../IRequest" ; import { NextFunction } from "../MiddlewareFactory" ; import ILogger from "../utils/ILogger" ; import { isURITemplateMatch } from "../utils/utils" ; export param { Context } context param { IRequest } req param { NextFunction } next param { ILogger } logger returns { void } export default function dispatchMiddleware ( context , req , next , logger ) { logger . verbose ( `DispatchMiddleware: Dispatching request...` , context . contextId ) ; let conditionsMet = - 1 ; for ( const key in Operation ) { if ( Operation . hasOwnProperty ( key ) ) { const operation = parseInt ( key , 10 ) ; const res = isRequestAgainstOperation ( req , Specifications [ operation ] , context . dispatchPattern ) ; if ( res [ 0 ] && res [ 1 ] > conditionsMet ) { context . operation = operation ; conditionsMet = res [ 1 ] ; } } } if ( context . operation === undefined ) { const handlerError = new UnsupportedRequestError ( ) ; logger . error ( `DispatchMiddleware: ${ handlerError . message }` , context . contextId ) ; return next ( handlerError ) ; } logger . info ( `DispatchMiddleware: Operation=${ Operation [ context . operation ] }` , context . contextId ) ; next ( ) ; } param { IRequest } req param { msRest . OperationSpec } spec returns { [ boolean , number ] } function isRequestAgainstOperation ( req , spec , dispatchPathPattern ? ) { let metConditionsNum = 0 ; if ( req === undefined || spec === undefined ) { return [ false , metConditionsNum ] ; } const xHttpMethod = req . getHeader ( "X-HTTP-Method" ) ; let method = req . getMethod ( ) ; if ( xHttpMethod && xHttpMethod . length > 0 ) { const value = xHttpMethod . trim ( ) ; if ( value === "GET" || value === "MERGE" || value === "PATCH" || value === "DELETE" ) { method = value ; } } if ( method !== spec . httpMethod ) { return [ false , metConditionsNum ++ ] ; } const path = spec . path ? spec . path . startsWith ( "/" ) ? spec . path : `/${ spec . path }` : "/" ; if ( ! isURITemplateMatch ( dispatchPathPattern !== undefined ? dispatchPathPattern : req . getPath ( ) , path ) ) { return [ false , metConditionsNum ++ ] ; } for ( const queryParameter of spec . queryParameters || [ ] ) { if ( queryParameter . mapper . required ) { const queryValue = req . getQuery ( queryParameter . mapper . serializedName || "" ) ; if ( queryValue === undefined ) { return [ false , metConditionsNum ] ; } if ( queryParameter . mapper . type . name === "Enum" && queryParameter . mapper . type . allowedValues . findIndex ( ( val ) => { return val === queryValue ; } ) < 0 ) { return [ false , metConditionsNum ] ; } if ( queryParameter . mapper . isConstant && queryParameter . mapper . defaultValue !== queryValue ) { return [ false , metConditionsNum ] ; } metConditionsNum ++ ; } } for ( const headerParameter of spec . headerParameters || [ ] ) { if ( headerParameter . mapper . required ) { const headerValue = req . getHeader ( headerParameter . mapper . serializedName || "" ) ; if ( headerValue === undefined ) { return [ false , metConditionsNum ] ; } if ( headerParameter . mapper . type . name === "Enum" && headerParameter . mapper . type . allowedValues . findIndex ( ( val ) => { return val === headerValue ; } ) < 0 ) { return [ false , metConditionsNum ] ; } if ( headerParameter . mapper . isConstant && `${ headerParameter . mapper . defaultValue || "" }` . toLowerCase ( ) !== headerValue . toLowerCase ( ) ) { return [ false , metConditionsNum ] ; } metConditionsNum ++ ; } } return [ true , metConditionsNum ] ; }