You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Compose环境中Blazor WASM调用GraphQL容器接口的URI适配方案

问题描述

我有一个Blazor WASM前端和GraphQL后端的解决方案,两者都已容器化且能独立正常运行。对应的docker-compose.yml配置如下:

version: "3.4"
name: search_and_map

services:
  blazor_wasm:
    image: fdq09eca/search_and_map-blazor_wasm
    build:
      context: .
      dockerfile: src/NDSH.Geospatial.Demos.SearchAndMap.Blazor/src/Dockerfile
    ports:
      - 8080:80
  graphql_api:
    image: fdq09eca/search_and_map-graphql_api
    build:
      context: .
      dockerfile: src/NDSH.Geospatial.Demos.SearchAndMap.Api/src/Dockerfile
    ports:
      - 51803:80

我在Blazor WASM中用以下代码向后端发送Post请求:

private async void GetAllBgsLayersFromGraphqlApi(MetadataSearchModel metadataSearchModel) {
        
        Uri graphqlApiUri = new Uri("http://search_and_map-graphql_api-1:80/graphql/");
      try {
        
        HttpClient client = new HttpClient();
        var queryContent = @"
query { 
  bgsLayers { 
    recordId,
    fileIdentifier,
    relatedDataSetUuId,
    operatesOnTitle,
    wmsLayerName,
    wmsLayerTitle,
    wmsLayerAbstract,
    wmsGetCapabilityUrl,
    arcGisMapServerUrl,
    arcGisLayerUrl,
    arcGisLayerName
  } 
}";
        var queryObject = new { query = queryContent };
        var queryJson = JsonConvert.SerializeObject(queryObject);
        
        var request = new HttpRequestMessage {
          RequestUri = graphqlApiUri,
          Method = HttpMethod.Post,
          Content = new StringContent(content: queryJson, encoding: System.Text.Encoding.UTF8, mediaType: "application/json"),
        };
        

        using (var response = await client.SendAsync(request)) {
          response.EnsureSuccessStatusCode();
          string responseString = await response.Content.ReadAsStringAsync();
          var obj = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, List<BgsLayer>>>>(responseString);
          metadataSearchModel.BgsLayers = obj!["data"]["bgsLayers"];
          return;
        }
      }
      catch (Exception ex) {
        System.Console.WriteLine("calling GraphQL API ERROR!!");
        System.Console.WriteLine($"[ERR] {ex.Message}");
        System.Console.WriteLine($"[uri] {graphqlApiUri.AbsolutePath}");

        throw;
      }
    }

但graphqlApiUri无法被正确解析,浏览器报错。本地环境用http://localhost:51803/graphql能正常运行,但在EC2实例上执行docker compose up后出现问题。请问如何正确解析URI,使其在本地和EC2环境都能正常工作?

解决方案

核心问题分析

Blazor WASM是浏览器端运行的应用,它的HTTP请求是从用户浏览器发起的,而非容器内部。你使用的search_and_map-graphql_api-1是Docker内部的服务名称,浏览器无法解析这个域名,这就是报错的根本原因。

具体解决步骤

1. 统一配置API地址

在Blazor WASM项目中通过环境配置文件管理API地址,避免硬编码:

  • 本地开发环境(appsettings.Development.json):
    {
      "GraphqlApiSettings": {
        "BaseUrl": "http://localhost:51803/graphql/"
      }
    }
    
  • EC2生产环境(appsettings.Production.json):
    {
      "GraphqlApiSettings": {
        "BaseUrl": "http://<EC2公网IP>:51803/graphql/"
      }
    }
    
    替换<EC2公网IP>为你的EC2实例实际公网IP或绑定的域名。

2. 注入配置到代码中

  • 先创建配置映射类:
    public class GraphqlApiSettings
    {
        public string BaseUrl { get; set; } = string.Empty;
    }
    
  • 在Program.cs中注册配置服务:
    builder.Services.Configure<GraphqlApiSettings>(builder.Configuration.GetSection("GraphqlApiSettings"));
    
  • 在组件中通过依赖注入获取配置:
    private readonly GraphqlApiSettings _apiSettings;
    
    public YourComponent(IOptions<GraphqlApiSettings> apiSettings)
    {
        _apiSettings = apiSettings.Value;
    }
    

3. 修改请求代码使用配置地址

把硬编码的URI替换为配置中的地址:

Uri graphqlApiUri = new Uri(_apiSettings.BaseUrl);

4. 本地Docker Compose优化(可选)

如果希望本地容器运行时自动读取正确地址,可在docker-compose.yml的blazor_wasm服务中添加环境变量:

blazor_wasm:
  # 原有配置...
  environment:
    - ASPNETCORE_ENVIRONMENT=Development
    - GraphqlApiSettings__BaseUrl=http://localhost:51803/graphql/

额外注意事项

  • 确保EC2实例的安全组开放了51803端口,允许外部访问。
  • 生产环境建议使用HTTPS,避免明文传输数据。

内容的提问来源于stack exchange,提问作者Chris LAM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:31:15