Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add interface for HTTP Respones in types package #529

Merged
merged 29 commits into from
Mar 4, 2022

Conversation

hossam-nasr
Copy link
Contributor

@hossam-nasr hossam-nasr commented Feb 10, 2022

Adds two interfaces for HTTP responses. Implements #169

Returning a response as an object

The HttpResponseObject interface defines the properties that the user can set when returning a response object in the HTTP module-like way. Those properties are passed to the host and define the response sent back to the client. An example of using this interface:

const httpTrigger: AzureFunction = async function(context: Context, req: HttpRequest): Promise<void> {
    context.res = {
        status: 200,
        body: "hello, world",
        headers: {
            hello: "world"
        }
   }
};

Returning a response using methods

The HttpResponseApi interface defines the methods exposed by the context.res object passed to the function when using HTTP triggers. This can be used to return a response in the express-like way. An example of using this interface:

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    context.res = context.res as HttpResponseApi;
    context.res.setHeader("hello", "world");
    context.res.status(200);
    context.res.body = "hello, world";
}; 

Design choices

The res property of the Context interface is set to be type HttpResponse = HttpResponseApi | HttpResponseObject

One challenge with implementing this interface is we need to support both ways of returning an HTTP response, both of which use the Context.res property. This means that context.res.setHeader(), for example, could be undefined. As a result, while JS code could use either ways of returning an HTTP response without an issue, TS code would throw an error when trying to call context.res.setHeader() without some sort of type guard/check to make sure the property is callable.

There are several ways to mitigate this. One way is to cast context.res to an HttpResponseApi object, as used above:

context.res = context.res as HttpResponseApi;
context.res.setHeader("hello", "world");

Another way would be to explicitly check the type of methods before calling them:

if(context.res?.status instanceof Function) {
    context.res.status(200)
}

Users can also define their own types and use those throughout their project:

export type ActualContext = Context & { res: HttpResponseApi }

const httpTrigger: AzureFunction = async function (context: ActualContext, req: HttpRequest): Promise<void> {
    context.res.status(200);
}; 

Whichever way this is done, TS code that called those functions without any checks, relying on the type of context.res being [key: string]: any will need at least some changes to continue working with no errors.

@hossam-nasr hossam-nasr requested review from ejizba and alrod February 11, 2022 00:37
Copy link
Contributor

@ejizba ejizba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than the names and one last comment, I think we're g2g

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants