跨域问题及html引用JavaScript脚本问题

        最近在学习 JavaScript,突然想到在上一家公司时跟前端同事调试 web 功能,然后就想着自己手动也搭一个 Http 的服务,这个服务是跑在一个 arm 设备上的,然后呢在局域网内在浏览器通过输入如 192.168.2.100:8000 这样来访问设备,如登录、获取配置、设置配置等等。因为是首次接触前端开发,也不知道怎么开始,然后就是简单地写了一个 html 文件,文件里引用了 js 代码,然后就在本地执行,首先遇到就是跨域问题,如:

 

直接在本地执行是不对的,肯定会出现跨域问题,真是第一次搞这个前端开发,啥也不懂啊,网上搜索了一番,需要从服务器返回一个 html 的文件,然后浏览器解析后再进行操作的。于是把这个index.html 文件拷贝到 arm 上,修改后如下:

 通过ip地址确实可以访问到了arm设备,默认返回的就是 index.html 的内容(这个是默认行为吗?不懂),然而新问题双出现了,如下:

loginbtn 没有定义,这个是一个函数,是我定义在js文件的函数,这个函数绑定到了 “登录” 按钮的 onclick 事件上,我的目的就是点击 “登录” 的时候,向服务器 POST 操作。很明显这里找不到这个函数定义。 以下是 index.html 的内容:

而 login.js 内容却是这样的:

这个内容是我的 http 服务器里应答的内容,奇怪这个怎么会这样?这个服务器程序是基于 mongoose 开源代码开发。一开始以为是 html 里指定的 js 加载路径写错了,网上搜索了好多基本上都是说路径写错导致无法加载到 js 代码,但其实不是,同时搜索到,js 文件是根据在 html 中的位置顺序加载的,也就是说浏览器也会去请求 js 文件,如上 <script src="login.js"></script>,所以浏览器是最后会去请求这个 login.js 文件,而我在 http 服务程序中回复了上面这个内容:

{
   "data" : "test"
}

所以导致 login.js 就成了这个,以至于那个函数没有定义。

 

所以还是服务端程序的问题。最新的 mongoose github 上的代码(版本是 "7.8")已经有例子,但它那个 js 代码对我这个初学者来说太难看懂了,我这个源码还是老版本的(版本是 "6.18")。错误的服务器代码响应是这样的:

浏览器来请求 login.js 的时候,服务器却应答了 “data”:"test" 的内容。我修改了服务端程序,简单到这样:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string>
#include <map>
#include <mutex>
#include "../webServer/mongoose.h"
#include "json/json.h"
#include "../webServer/webServer.h"
#include "comm/log.h"

void eventHandler(struct mg_connection *nc, int event, void *eventData);
void handleRequest(struct mg_connection *connection, int32_t event, void *data);
void* addConnection(struct mg_connection *nc);
void delConnection(void *usrData);

const char *sgWorkPath = "/web";

struct userData
{
    int index;
};

struct FileInfo
{
    FILE *fp;
    char fileName[32];
    char filePath[32];
    size_t size;
};

std::map<std::string, std::string> g_headerMap;
std::map<int, void *> g_connectionMap; //连接映射表,当多线程时,用于找到对应连接进行应答
std::string g_protocol; //协议,如http /1.1
std::string g_stateStr; //状态描述,用于返回应答

int g_status = 200;  //应答状态
int g_connectId = 0; //连接id的分配

std::mutex g_mutex;

//用postman 测试,linux需要关闭防火墙,否则收不到数据
int main(int argc, char *argv[])
{   
    if(argc < 2)
    {
        errorf("Usage: %s port\n", argv[0]);
        return 1;
    }

    int port = atoi(argv[1]);

    struct userData uData{100};
    struct mg_mgr mgr;

    //mgr里的user_data指针将会指向第二个参数,当有连接过来时
    //mg_connection中的mgr中的user_data指向的就是第二个参数
    mg_mgr_init(&mgr, &uData);

    char buf[32] = {0};
    snprintf(buf, sizeof(buf), "%d", port);
    struct mg_connection *con = mg_bind(&mgr, buf, eventHandler);

    if(con == NULL) {
        errorf("mg_bind fail\n");
        return -1;
    }

    mg_set_protocol_http_websocket(con);

    uData.index = 200;
    infof("listen ip[%s], port[%d]....\n", inet_ntoa(con->sa.sin.sin_addr), port);

    while (1)
    {
        mg_mgr_poll(&mgr, 100);
    }
    
    mg_mgr_free(&mgr);
    return 0;
}

void eventHandler(struct mg_connection *nc, int event, void *eventData)
{
    switch (event)
    {
        case MG_EV_ACCEPT:
            // tracef("a new accept!!\n");
            // nc->user_data = addConnection(nc); //delConnection时用uc进行connctionID的传递
            break;
        case MG_EV_HTTP_REQUEST:
            // tracef("a new http request!!\n");      
            handleRequest(nc, event, eventData);
            break;
        case MG_EV_CLOSE:
            // tracef("request close!!\n");
            delConnection(nc->user_data);
            nc->user_data = nullptr;
            break;
        default:
            break;
    }
}

// 添加一个连接
void* addConnection(struct mg_connection *nc)
{
    userData *data = new userData; //此内存在delConnection时进行释放
    std::lock_guard<std::mutex> lockGuard(g_mutex);
    g_connectId += 1;
    data->index = g_connectId;
    g_connectionMap.insert(std::pair<int, void*>(g_connectId, nc));

    return data;
}

// 删除一个连接
void delConnection(void *usrData)
{
    userData *data = (userData*)usrData;
    if(data == NULL)
    {
        return;
    }

    if(g_connectionMap.find(data->index) != g_connectionMap.end())
    {
        tracef("delete connection id: %d\n", data->index);
        g_connectionMap.erase(data->index);
    }
    delete data; //释放addConnection时申请的内存
}

void setServerPath(struct mg_connection *connection, struct http_message* msg, const char *path)
{
    warnf("set server path: %s\n", path);
    struct mg_serve_http_opts opts;
    memset(&opts, 0, sizeof(opts));
    opts.enable_directory_listing = "yes";
    opts.document_root = path;
    mg_serve_http(connection, msg, opts);
}

void handleRequest(struct mg_connection *connection, int32_t event, void *data)
{
    struct http_message* msg = (struct http_message*)data;

    //请求正文
    std::string body(msg->body.p, msg->body.len);
    if(body.length() > 0)
    {
        tracef("body size: %u, %s\n", body.length(), body.c_str());
    }

    //请求的地址,不包括ip地址和端口号
    std::string uri(msg->uri.p, msg->uri.len);

    //请求的方法,GET、POST、PUT等
    std::string method(msg->method.p, msg->method.len);
    tracef("connect from ip: %s, method = %s, uri = %s\n", inet_ntoa(connection->sa.sin.sin_addr), method.c_str(), uri.c_str());    

    //设置资源根目录
    if(uri == "/api/user/login/")
    {

    }
    else 
    {
        setServerPath(connection, msg, sgWorkPath);
        return;
    }
}

最后 login.js 加载成功了

 

这样才能接着往下添加新的功能了。 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,可以通过以下方式解决跨域问题: 1. 使用 CORS(Cross-Origin Resource Sharing):CORS是一种机制,允许服务器在响应请求时设置响应头,从而允许跨域访问。在Java中,可以通过在Servlet中设置响应头实现CORS。具体做法是在Servlet的doGet()或doPost()方法中添加以下代码: resp.setHeader("Access-Control-Allow-Origin", "*"); resp.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); resp.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); 其中,Access-Control-Allow-Origin指定允许跨域访问的域名,*表示允许所有域名访问。Access-Control-Allow-Methods指定允许的请求方法,Access-Control-Allow-Headers指定允许的请求头。 2. 使用 JSONP(JSON with Padding):JSONP是一种跨域解决方案,它通过在请求URL中添加一个回调函数名,让服务器返回一个JavaScript脚本,该脚本调用回调函数并将数据作为参数传递给回调函数。在Java中,可以通过在Servlet中返回一个JavaScript脚本实现JSONP。具体做法是在Servlet的doGet()或doPost()方法中添加以下代码: String callback = request.getParameter("callback"); String data = "{ \"name\": \"张三\", \"age\": 20 }"; String result = callback + "(" + data + ")"; response.getWriter().write(result); 其中,callback是从请求URL中获取的回调函数名,data是要返回的JSON数据,result是将data作为参数传递给回调函数后的JavaScript脚本。 以上两种方式都可以解决跨域问题,但CORS更为安全、灵活,而JSONP则更为简单、易用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值