data-api-builder icon indicating copy to clipboard operation
data-api-builder copied to clipboard

[Bug]: GraphQL request redirected to favicon.ico

Open JerryNixon opened this issue 1 year ago • 4 comments

What happened?

Navigated to https://localhost:5001

Console:

info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
      Route matched with {action = "Find", controller = "Rest"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] Find(System.String) on controller Azure.DataApiBuilder.Service.Controllers.RestController (Azure.DataApiBuilder.Service).
fail: Azure.DataApiBuilder.Service.Controllers.RestController[0]
      02f4732e-ab4e-4f7b-acbb-d07f758a5384: GraphQL request redirected to favicon.ico.
fail: Azure.DataApiBuilder.Service.Controllers.RestController[0]
      02f4732e-ab4e-4f7b-acbb-d07f758a5384:    at Azure.DataApiBuilder.Service.Controllers.RestController.HandleOperation(String route, EntityActionOperation operationType)
info: Microsoft.AspNetCore.Mvc.Infrastructure.SystemTextJsonResultExecutor[1]
      Executing JsonResult, writing value of type '<>f__AnonymousType0`1[[<>f__AnonymousType1`3[[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Azure.DataApiBuilder.Service, Version=0.8.52.0, Culture=neutral, PublicKeyToken=null]]'.

Configuration:

{
  "$schema": "https://github.com/Azure/data-api-builder/releases/download/v0.8.52/dab.draft.schema.json",
  "data-source": {
    "database-type": "mssql",
    "connection-string": "@env('my-connection-string')"
  },
  "runtime": {
    "rest": {
      "enabled": true,
      "path": "/api"
    },
    "graphql": {
      "enabled": false
    },
    "host": {
      "cors": {
        "origins": [],
        "allow-credentials": false
      },
      "authentication": {
        "provider": "StaticWebApps"
      },
      "mode": "development"
    }
  },
  "entities": {
    "PageCustomers": {
      "source": {
        "object": "[dbo].[PageCustomers]",
        "type": "stored-procedure",
        "parameters": {
          "PageSize": "",
          "StartIndex": ""
        }
      },
      "graphql": {
        "enabled": false
      },
      "rest": {
        "enabled": true
      },
      "permissions": [
        {
          "role": "anonymous",
          "actions": [ "execute" ]
        }
      ]
    }
  }
}

SQL schema:

CREATE PROCEDURE PageCustomers
    @StartIndex INT = 1,
    @PageSize INT
AS
BEGIN
    SELECT [Id], [Name], [City], [State]
    FROM Customers
    ORDER BY Name
    OFFSET (@StartIndex - 1) * @PageSize ROWS
    FETCH NEXT @PageSize ROWS ONLY;
END

CREATE TABLE Customers
(
      Id INT PRIMARY KEY IDENTITY(1, 1)
    , Name NVARCHAR(50) NULL
    , City VARCHAR(MAX) NOT NULL
    , State VARCHAR(50) NOT NULL DEFAULT 'CO'
    , Location AS (City + ', ' + State) PERSISTED
    , SpecialRank DECIMAL(18, 2) NOT NULL DEFAULT 0
)

Version

Microsoft.DataApiBuilder 0.8.52+c69925060e1942d28515b9c4b89ea24832da0c7c

What database are you using?

Azure SQL

What hosting model are you using?

Local (including CLI)

Which API approach are you accessing DAB through?

REST

Relevant log output

C:\Temp\dab>dab start
Information: Microsoft.DataApiBuilder 0.8.52+c69925060e1942d28515b9c4b89ea24832da0c7c
Information: Config not provided. Trying to get default config based on DAB_ENVIRONMENT...
Information: Environment variable DAB_ENVIRONMENT is (null)
Loading config file from dab-config.json.
Information: Loaded config file: dab-config.json
Information: Setting default minimum LogLevel: Debug for Development mode.
Starting the runtime engine...
Loading config file from dab-config.json.
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[63]
      User profile is available. Using 'C:\Users\jerry\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
info: Azure.DataApiBuilder.Core.Services.ISqlMetadataProvider[0]
      PageCustomers path: /api/PageCustomers
dbug: Azure.DataApiBuilder.Core.Resolvers.IQueryExecutor[0]
      Executing query:
SELECT name as result_field_name, TYPE_NAME(system_type_id) as result_type, is_nullable FROM sys.dm_exec_describe_first_result_set_for_object (OBJECT_ID('dbo.PageCustomers'), 0) WHERE is_hidden is not NULL AND is_hidden = 0
dbug: Azure.DataApiBuilder.Core.Services.ISqlMetadataProvider[0]
      Logging primary key information for entity: PageCustomers.
info: Azure.DataApiBuilder.Core.Configurations.RuntimeConfigValidator[0]
      Validating Relationship Section in Config...
info: Azure.DataApiBuilder.Service.Startup[0]
      Successfully completed runtime initialization.
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\Temp\dab
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/ - -
dbug: Azure.DataApiBuilder.Core.AuthenticationHelpers.ClientRoleHeaderAuthenticationMiddleware[0]
      4dd1aa81-0cfa-42b6-bd61-b3b234ad3700: Request authentication state: Anonymous.
dbug: Azure.DataApiBuilder.Core.AuthenticationHelpers.ClientRoleHeaderAuthenticationMiddleware[0]
      4dd1aa81-0cfa-42b6-bd61-b3b234ad3700: The request will be executed in the context of Anonymous role
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'Health checks'
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'Health checks'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/2 GET https://localhost:5001/ - - - 200 - text/plain 23.9130ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/favicon.ico - -
dbug: Azure.DataApiBuilder.Core.AuthenticationHelpers.ClientRoleHeaderAuthenticationMiddleware[0]
      b388e75c-ea75-41c8-8d20-e64151c27bcc: Request authentication state: Anonymous.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'Azure.DataApiBuilder.Service.Controllers.RestController.Find (Azure.DataApiBuilder.Service)'
dbug: Azure.DataApiBuilder.Core.AuthenticationHelpers.ClientRoleHeaderAuthenticationMiddleware[0]
      b388e75c-ea75-41c8-8d20-e64151c27bcc: The request will be executed in the context of Anonymous role
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
      Route matched with {action = "Find", controller = "Rest"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] Find(System.String) on controller Azure.DataApiBuilder.Service.Controllers.RestController (Azure.DataApiBuilder.Service).
fail: Azure.DataApiBuilder.Service.Controllers.RestController[0]
      b388e75c-ea75-41c8-8d20-e64151c27bcc: GraphQL request redirected to favicon.ico.
fail: Azure.DataApiBuilder.Service.Controllers.RestController[0]
      b388e75c-ea75-41c8-8d20-e64151c27bcc:    at Azure.DataApiBuilder.Service.Controllers.RestController.HandleOperation(String route, EntityActionOperation operationType)
info: Microsoft.AspNetCore.Mvc.Infrastructure.SystemTextJsonResultExecutor[1]
      Executing JsonResult, writing value of type '<>f__AnonymousType0`1[[<>f__AnonymousType1`3[[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Azure.DataApiBuilder.Service, Version=0.8.52.0, Culture=neutral, PublicKeyToken=null]]'.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
      Executed action Azure.DataApiBuilder.Service.Controllers.RestController.Find (Azure.DataApiBuilder.Service) in 20.2691ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'Azure.DataApiBuilder.Service.Controllers.RestController.Find (Azure.DataApiBuilder.Service)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/2 GET https://localhost:5001/favicon.ico - - - 400 - application/json;+charset=utf-8 39.3177ms
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

JerryNixon avatar Oct 11 '23 23:10 JerryNixon

There are two parts to this bug:

  1. Why doesn't it work?
  2. This error message is useless to the developer.

JerryNixon avatar Oct 11 '23 23:10 JerryNixon

  1. This error is emitted into the logs because a browser attempts to load a favicon.ico file to display in the browser tab. Since DAB is an API endpoint, this type of request isn't honored. As an API, DAB would respond to direct requests for resources instead of the many requests a browser may try to send. Here is a screenshot of loading https://localhost:5001 in the browser: image

  2. Agreed. We probably shouldn't return this error or should offer a way to mitigate.

seantleonard avatar Oct 12 '23 01:10 seantleonard

Closing criteria:

  • Change how DAB alerts/logs to failed favicon requests by disabling ASP.NET logs by default in appsettings.json in favor of DAB only displaying DAB specific logs.
  • DAB should not log favicon.ico requests as failures that imply something is wrong with DAB normal operation.
  • DAB should return 404 Not Found and not 400 Bad request for favicon requests.

Context:

The following events are logged to the console for every favicon.ico request:

fail: Azure.DataApiBuilder.Service.Controllers.RestController[0] b388e75c-ea75-41c8-8d20-e64151c27bcc: GraphQL request redirected to favicon.ico. fail: Azure.DataApiBuilder.Service.Controllers.RestController[0] b388e75c-ea75-41c8-8d20-e64151c27bcc: at Azure.DataApiBuilder.Service.Controllers.RestController.HandleOperation(String route, EntityActionOperation operationType)

A favicon request is a valid and expected requests from a web browser. The DAB API endpoint has no file to return because it is not meant to be browser/user facing (no GUI). DAB is really only meant to be accessed directly within a browser when a developer is actively building a DAB solution.

Production deployed apps will use DAB behind the scenes with HTTP requests to the exposed API endpoints.

seantleonard avatar Jan 08 '24 21:01 seantleonard

Moving to 1.1rc to potentially clean up.

Aniruddh25 avatar Apr 04 '24 18:04 Aniruddh25