我正在尝试制作一个客户端-服务器应用程序,并且我正在尝试通过 REST API 将数据从我的服务器发送到我的客户端。在服务器端,我将 Django 与 Django REST Framework 一起使用,我配置了代码来处理请求,如下所示:
from .models import Song
from .serializers import SongSerializer
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
@api_view(['GET', 'POST'])
def song_list(request, format=None):
# get all Songs
# serialize
# return JSON
if request.method == 'GET':
songs = Song.objects.all()
serializer = SongSerializer(songs, many=True)
return Response(serializer.data)
if request.method == 'POST':
serializer = SongSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
@api_view(['GET', 'PUT', 'DELETE'])
def song_detail(request, id, format=None):
try:
song = Song.objects.get(pk=id)
except Song.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = SongSerializer(song)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = SongSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
song.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
当我使用 python 使用 API 时,它可以很容易地使用这段代码(我根据需要获取 JSON 数据)
import requests
response = requests.get("http://127.0.0.1/api/")
print(response.json)
但是从客户端,我在 GET 请求中得到的只是 HTTP 响应标头。这是我的客户端代码:
/* Sockets Example
* Copyright (c) 2016-2020 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "mbed-trace/mbed_trace.h"
#include "wifi_helper.h"
class SocketInterface {
static constexpr size_t MAX_NUMBER_OF_ACCESS_POINTS = 10;
static constexpr size_t MAX_MESSAGE_RECEIVED_LENGTH = 100;
static constexpr size_t REMOTE_PORT = 80; // standard HTTP port
public:
SocketInterface() : net(NetworkInterface::get_default_instance())
{
}
~SocketInterface()
{
if (net) {
net->disconnect();
}
}
void run()
{
if (!net) {
printf("Error! No network interface found.\r\n");
return;
}
/* if we're using a wifi interface run a quick scan */
if (net->wifiInterface())
{
/* the scan is not required to connect and only serves to show visible access points */
wifi_scan();
/* in this example we use credentials configured at compile time which are used by
* NetworkInterface::connect() but it's possible to do this at runtime by using the
* WiFiInterface::connect() which takes these parameters as arguments */
}
/* connect will perform the action appropriate to the interface type to connect to the network */
printf("Connecting to the network...\r\n");
nsapi_size_or_error_t result = net->connect();
if (result != 0)
{
printf("Error! net->connect() returned: %d\r\n", result);
return;
}
print_network_info();
/* opening the socket only allocates resources */
result = socket.open(net);
if (result != 0)
{
printf("Error! socket.open() returned: %d\r\n", result);
return;
}
/* now we have to find where to connect */
SocketAddress* address = new SocketAddress("192.168.100.88", 80);
// if (!resolve_hostname(address))
// {
// return;
// }
// address.set_port(REMOTE_PORT);
/* we are connected to the network but since we're using a connection oriented
* protocol we still need to open a connection on the socket */
printf("Opening connection to remote port %d\r\n", REMOTE_PORT);
result = socket.connect(*address);
if (result != 0)
{
printf("Error! socket.connect() returned: %d\r\n", result);
return;
}
/* exchange an HTTP request and response */
if (!send_http_request())
{
return;
}
if (!receive_http_response())
{
return;
}
printf("Demo concluded successfully \r\n");
}
private:
bool resolve_hostname(SocketAddress &address)
{
const char hostname[] = MBED_CONF_APP_HOSTNAME;
/* get the host address */
printf("\nResolve hostname %s\r\n", hostname);
nsapi_size_or_error_t result = net->gethostbyname(hostname, &address);
if (result != 0)
{
printf("Error! gethostbyname(%s) returned: %d\r\n", hostname, result);
return false;
}
printf("%s address is %s\r\n", hostname, (address.get_ip_address() ? address.get_ip_address() : "None") );
return true;
}
bool send_http_request()
{
/* loop until whole request sent */
const char buffer[] = "GET /api/ HTTP/1.1\r\n"
"\r\n";
nsapi_size_t bytes_to_send = strlen(buffer);
nsapi_size_or_error_t bytes_sent = 0;
printf("\r\nSending message: \r\n%s", buffer);
while (bytes_to_send)
{
bytes_sent = socket.send(buffer + bytes_sent, bytes_to_send);
if (bytes_sent < 0)
{
printf("Error! socket.send() returned: %d\r\n", bytes_sent);
return false;
}
else
{
printf("sent %d bytes\r\n", bytes_sent);
}
bytes_to_send -= bytes_sent;
}
printf("Complete message sent\r\n");
return true;
}
bool receive_http_response()
{
char buffer[MAX_MESSAGE_RECEIVED_LENGTH];
int remaining_bytes = MAX_MESSAGE_RECEIVED_LENGTH;
int received_bytes = 0;
/* loop until there is nothing received or we've ran out of buffer space */
nsapi_size_or_error_t result = remaining_bytes;
while (result > 0 && remaining_bytes > 0)
{
result = socket.recv(buffer + received_bytes, remaining_bytes);
if (result < 0)
{
printf("Error! socket.recv() returned: %d\r\n", result);
return false;
}
received_bytes += result;
remaining_bytes -= result;
}
/* the message is likely larger but we only want the HTTP response code */
printf("received: %s\r\n\r\n", buffer);
// printf("received %d bytes:\r\n%.*s\r\n\r\n", received_bytes, strstr(buffer, "\n") - buffer, buffer);
return true;
}
void wifi_scan()
{
WiFiInterface *wifi = net->wifiInterface();
WiFiAccessPoint ap[MAX_NUMBER_OF_ACCESS_POINTS];
/* scan call returns number of access points found */
int result = wifi->scan(ap, MAX_NUMBER_OF_ACCESS_POINTS);
if (result <= 0) {
printf("WiFiInterface::scan() failed with return value: %d\r\n", result);
return;
}
printf("%d networks available:\r\n", result);
for (int i = 0; i < result; i++) {
printf("Network: %s secured: %s BSSID: %hhX:%hhX:%hhX:%hhx:%hhx:%hhx RSSI: %hhd Ch: %hhd\r\n",
ap[i].get_ssid(), get_security_string(ap[i].get_security()),
ap[i].get_bssid()[0], ap[i].get_bssid()[1], ap[i].get_bssid()[2],
ap[i].get_bssid()[3], ap[i].get_bssid()[4], ap[i].get_bssid()[5],
ap[i].get_rssi(), ap[i].get_channel());
}
printf("\r\n");
}
void print_network_info()
{
/* print the network info */
SocketAddress a;
net->get_ip_address(&a);
printf("IP address: %s\r\n", a.get_ip_address() ? a.get_ip_address() : "None");
net->get_netmask(&a);
printf("Netmask: %s\r\n", a.get_ip_address() ? a.get_ip_address() : "None");
net->get_gateway(&a);
printf("Gateway: %s\r\n", a.get_ip_address() ? a.get_ip_address() : "None");
}
private:
NetworkInterface *net;
TCPSocket socket;
};
int main()
{
printf("\n");
printf("************************************************************\n");
printf("*** STM32 IoT Discovery kit for STM32L475 MCU ***\n");
printf("*** WIFI Web Server demonstration ***\n");
printf("*** Update the LED status ***\n");
printf("************************************************************\n");
SocketInterface *sockIf = new SocketInterface();
MBED_ASSERT(sockIf);
sockIf->run();
return 0;
}
我收到的缓冲区是这样的:
我在 B-L475VG-IOT01A 板上使用 MBED 操作系统。
任何帮助将不胜感激!
我已经发出了 GET 请求,但我不知道如何访问 JSON 数据