React Native 如何将Expo GO应用程序连接到本地主机上的Django Rest Framework后端?

q3qa4bjr  于 2023-01-05  发布在  React
关注(0)|答案(1)|浏览(207)

我正在使用Expo实现一个react原生应用,并使用Expo Go在我的iOS设备上测试它。我的本地机器上运行着Django rest框架后端,我可以使用浏览器通过http://localhost:8000访问它-在我的react原生应用中使用localhost在我的获取请求期间不起作用。例如:

let response = await fetch(BACKEND_URL + "/shft/auth/token/obtain/", {
      method: "POST",
      body: JSON.stringify(data),
      headers: {
        "Content-Type": "application/json",
      },
    });

退货

Network request failed
at node_modules\whatwg-fetch\dist\fetch.umd.js:null in setTimeout$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:null in _allocateCallback$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:null in _callTimer
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:null in callTimers
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:null in __callFunction
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:null in __guard$argument_0
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:null in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:null in callFunctionReturnFlushedQueue

我尝试过将BACKEND_URL设置为localhost:8000,并通过expo-constants设置我的公共IP

import Constants from "expo-constants";

const { manifest } = Constants;

const uri = `http://${manifest.debuggerHost.split(":").shift()}:8000`;

但似乎都不起作用。我已经在我的DRF项目中启用了Corsheaders中间件,并在APIView的调度方法上放置了@csrf_exempt装饰器,但这个错误仍然存在。我还在CORS白名单中添加了localhost:19000,这似乎是Expo托管其本地服务器的地方。这里可能有什么问题?Expo服务器和Django服务器都在我的笔记本电脑上本地运行,否则API在Django测试中工作。
通过localhost在我的API端点上使用curl也可以,尽管expo常量返回的外部IP不能--但这可能是因为我是从localhost发送的。

643ylb08

643ylb081#

我发现了一个修复使用这两个职位的信息:这个stack overflow和这个blog。这两个解决方案都不适合我,但是一点网络逻辑让它们结合在一起。这里的核心问题是Django服务器托管在本地,而Expo Go应用程序运行在单独的移动设备上(尽管expo服务器也是本地托管的)。我已经测试了下面的每一个步骤,以确保它们都是必要的。
1.使用corsheaders应用程序和相应的中间件设置Django CORS,有关于如何操作的指南,但基本上是pip install django-cors-headers,然后将其添加到您的INSTALLED_APPS和settings.py中的中间件

INSTALLED_APPS = [
    ...,
    'corsheaders',
]

# make sure CorsMiddleware comes before CommonMiddleware
MIDDLEWARE = [
    ...,
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...,

]

此外,在必须能够访问的视图上使用@csrf_exempt装饰器(这涉及到安全问题,但我对这个移动应用使用的是JWT身份验证,所以在我的情况下这是可以的-我会在这里进行尽职调查)。对于函数和类视图,有几种方法可以做到这一点:

from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def my_view():
...

# or for class based views
class my_view(APIView):
  @csrf_exempt
  def dispatch(self, request, *args, **kwargs):
    return super().dispatch(self, request, *args, **kwargs)

# or my preferred way for easy copy paste
@method_decorator(csrf_exempt, name='dispatch')
class my_view(APIView):
...

1.通过局域网暴露Django服务器,这一步是必要的,这样你的设备就可以通过局域网与Django服务器连接--如果使用模拟器,这一步可能就不必要了(尽管我知道Android模拟器使用一个特别指定的IP地址访问localhost,所以我会检查这一点)。

# specify this IP to expose on LAN
python manage.py runserver 0.0.0.0:8000

1.找到你本地机器的IP地址--上面的博客使用了移动设备的IP地址,但对我来说不起作用,这是有意义的,因为两个服务器都在我的笔记本电脑上运行。对于windows,我打开命令提示符,输入ipconfig,然后找到IPv4......行,其中包含我的地址。

  1. Use this IP to direct your API calls and add it to your CORS whitelist. For example if your localmachine IP is 10.0.0.1 and Expo is on port 19000 while Django is on port 8000 we add the following.
    一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个

相关问题