2017-02-11 28 views
8

Tôi sau các url chuẩn hóa/chuẩn hóa cho SPA với máy chủ ExpressJS.ExpressJS các url chuẩn hóa/chuẩn hóa

Mặc dù SPA được sao lưu bởi bộ định tuyến phía máy chủ - mẫu có thể khác một chút đối với url ứng dụng. Một trong những điểm khác biệt là thẻ <link rel="canonical" href="https://example.com{{ originalPath }}">. Không phải chi tiết có liên quan nhưng giải thích ngữ cảnh của câu hỏi. Tôi hy vọng rằng sẽ chỉ có một URL phản hồi với 200, các biến thể của nó được chuyển hướng đến với 301/302 (hoạt động cho con người và công cụ tìm kiếm).

Tôi muốn làm cho url trở nên nhạy cảm và nghiêm ngặt (không có dấu gạch chéo), tương tự như các tùy chọn Router, nhưng các url không chuẩn (khác biệt trong trường hợp hoặc dấu gạch chéo) nên chuyển hướng 301/302 sang url chuẩn thay vì 404.

Trong hầu hết các ứng dụng, tôi chỉ muốn buộc các url cho các tuyến đường có mức độ thấp hơn (ngoại trừ các truy vấn), không có dấu gạch chéo thêm. I E. app.all('*', ...) và các chuyển hướng là:

/Foo/Bar/ -> /foo/bar 
/foo/Bar?Baz -> /foo/bar?Baz 

Nhưng có thể có ngoại lệ nếu các tuyến đường được xác định rõ ràng. Ví dụ, có những tuyến đường lạc đà-cased:

possiblyNestedRouter.route('/somePath')... 
possiblyNestedRouter.route('/anotherPath/:Param')... 

Và tất cả các url không kinh điển nên được chuyển hướng đến kinh điển (trường hợp tham số còn lại nguyên vẹn):

/somepath/ -> /somePath 
/anotherpath/FOO -> /anotherPath/FOO 

Logic đằng sau url kinh điển là khá đơn giản, vì vậy thật lạ khi tôi không thể tìm thấy bất cứ điều gì về chủ đề này liên quan đến ExpressJS.

Cách tốt nhất để làm điều này là gì? Có middlewares đã có thể giúp đỡ?

Trả lời

4

Tôi đã tìm kiếm npms, tôi không thể tìm thấy bất kỳ thứ gì, vì vậy điều này đã làm xước đầu tôi và tôi đã mã hóa một nhiệm vụ nhỏ cho express để thực hiện cho từng yêu cầu. Vui lòng thêm mã này vào mã của bạn.

var urls = { 
    '/main' : '/main', 
    '/anotherMain' : '/anotherMain' 
} 

app.use(function(req, res, next){ 

    var index = req.url.lastIndexOf('/'); 

    //We are checking to see if there is an extra slash first 
    if(req.url[index+1] == null || req.url[index+1] == undefined || req.url[index+1] == '/'){ 
    //slashes are wrong 
    res.send("please enter a correct url"); 
    res.end(); 
    }else{ 

     for(var item in urls){ 
     if(req.url != item && req.url.toUpperCase() == item.toUpperCase()){ 
      res.redirect(item); 
      console.log("redirected"); 
      //redirected 
     }else if (req.url == item) { 
      console.log("correct url"); 
      next(); 
     }else{ 
      //url doesn't exist 
     } 
    } 

    } 
    next(); 

}); 

app.get('/main', function(req, res){ 
    res.render('mainpage'); 
}); 

app.get('/anotherMain', function(req, res){ 
    res.send("here here"); 
}); 

SỬ DỤNG

Tất cả bạn phải làm là, thêm đối tượng url-urls của bạn như thực hiện trên bằng cho nó giá trị khóa tương tự. Đó là nó. Xem cách dễ dàng là. Bây giờ tất cả yêu cầu của khách hàng của bạn sẽ được chuyển hướng đến trang chính xác trường hợp nhạy cảm.

CẬP NHẬT

tôi cũng đã thực hiện một cho POST yêu cầu, tôi nghĩ rằng đó là khá chính xác, bạn cũng nên cung cấp cho nó một thử. Ff bạn muốn chuyển hướng khi người dùng trộn các dấu gạch chéo, bạn cần phải viết một số regex cho nó. Tôi không có thời gian mà não của tôi cũng bị rán nên tôi đã làm một cái đơn giản. Bạn có thể thay đổi nó theo ý bạn. Mỗi cấu trúc web đều có bộ quy tắc riêng.

var urlsPOST = { 
    '/upload' : '/upload' 
} 

app.use(function(req, res, next){ 

    if(req.method == 'POST'){ 

    var index = req.url.lastIndexOf('/'); 

    if(req.url[index+1] == null || req.url[index+1] == undefined || req.url[index+1] == '/'){ 

     //slashes are wrong 
     res.sendStatus(400); 
     res.end(); 
     return false; 

    }else{ 

     for(var item in urlsPOST){ 
      if(req.url != item && req.url.toUpperCase() == item.toUpperCase()){ 
      res.redirect(307, item); 
      res.end(); 
      return false; 
      //redirected 

      }else if (req.url == item) { 
      console.log("correct url"); 
      next(); 

      }else{ 
      res.sendStatus(404).send("invalid URL"); 
      return false; 
      //url doesn't exist 
      } 
     } 
    } 
    } 
    next(); 
}); 
1

Có thể bạn muốn viết middleware của riêng bạn cho điều này, một cái gì đó dọc theo dòng này:

app.set('case sensitive routing', true); 
 

 
/* all existing routes here */ 
 

 
app.use(function(req, res, next) { 
 
    var url = find_correct_url(req.url); // special urls only 
 
    if(url){ 
 
    res.redirect(url); // redirect to special url 
 
    }else if(req.url.toLowerCase() !=== req.url){ 
 
    res.redirect(req.url.toLowerCase()); // lets try the lower case version 
 
    }else{ 
 
    next(); // url is not special, and is already lower case 
 
    }; 
 
});

Bây giờ hãy ghi nhớ middleware này có thể được đặt sau khi tất cả các tuyến đường hiện tại của bạn , do đó nếu nó không phù hợp với một lộ trình hiện tại, bạn có thể cố gắng tìm kiếm những gì nó cần. Nếu bạn đang sử dụng tuyến đường không phân biệt chữ hoa chữ thường, bạn sẽ muốn thực hiện điều này trước tuyến đường của mình.

+0

Nhưng còn những yêu cầu không được GET thì sao? Và những gì về các trường hợp nhạy cảm với chữ như 'somePath'? Chúng có thể được gắn kết các tuyến đường, tức là đoạn tuyến sẽ không là tuyến đầu tiên sau URL ban đầu '/' trong url. – estus

+1

điều này sẽ nhận được tất cả các loại tuyến đường, tuy nhiên bạn chỉ có thể thực hiện chuyển hướng trên yêu cầu GET và bảo toàn tất cả nội dung. Nếu bạn muốn cố gắng thực hiện một số kết hợp thông minh hơn (sau khi chèn độ nhạy chữ hoa trên dòng 1), bạn có thể sử dụng app._router.stack để liệt kê tất cả các tuyến đường và cố gắng tìm phần chữ nhạy cảm –

0

Sử dụng cùng mã như @ user8377060 chỉ với một regex thay thế.

// an array of all my urls 
    var urls = [ 
    '/main', 
    '/anotherMain' 
    ] 

    app.use(function(req, res, next){ 

    var index = req.url.lastIndexOf('/'); 

    //We are checking to see if there is an extra slash first 
    if(req.url[index+1] == null || req.url[index+1] == undefined || req.url[index+1] == '/'){ 
    //slashes are wrong 
    res.send("please enter a correct url"); 
    res.end(); 
    }else{ 

     for(var item in urls){ 
     var currentUrl = new RegExp(item, 'i'); 

     if(req.url != item && currentUrl.test(item)){ 
      res.redirect(item); 
      console.log("redirected"); 
      //redirected 
     }else if (req.url == item) { 
      console.log("correct url"); 
      next(); 
     }else{ 
      //url doesn't exist 
     } 
    } 

    } 
    next(); 

    }); 
+1

Cảm ơn ý tưởng. Tuy nhiên, tôi không thấy lý do để sử dụng 'RegExp' mới. Nó đòi hỏi phải thoát. Nó sẽ phù hợp với phân đoạn lỏng lẻo, điều này không được mong muốn nói chung. Các phân đoạn url trong 'url' có thể được thực hiện regexps nếu chúng được cho là regexps. – estus

Các vấn đề liên quan