การใช้ส่วนหัวการให้สิทธิ์กับดึงข้อมูลในการตอบสนองแบบเนทีฟ


141

ฉันกำลังพยายามใช้fetchใน React Native เพื่อดึงข้อมูลจาก Product Hunt API ฉันได้รับโทเค็นการเข้าถึงที่เหมาะสมและบันทึกไว้ในสถานะแล้ว แต่ดูเหมือนจะไม่สามารถส่งต่อได้ภายในส่วนหัวการให้สิทธิ์สำหรับคำขอ GET

นี่คือสิ่งที่ฉันมี:

var Products = React.createClass({
  getInitialState: function() {
    return {
      clientToken: false,
      loaded: false
    }
  },
  componentWillMount: function () {
    fetch(api.token.link, api.token.object)
      .then((response) => response.json())
      .then((responseData) => {
          console.log(responseData);
        this.setState({
          clientToken: responseData.access_token,
        });
      })
      .then(() => {
        this.getPosts();
      })
      .done();
  },
  getPosts: function() {
    var obj = {
      link: 'https://api.producthunt.com/v1/posts',
      object: {
        method: 'GET',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + this.state.clientToken,
          'Host': 'api.producthunt.com'
        }
      }
    }
    fetch(api.posts.link, obj)
      .then((response) => response.json())
      .then((responseData) => {
        console.log(responseData);
      })
      .done();
  },

ความคาดหวังที่ฉันมีสำหรับรหัสของฉันคือ:

  1. ก่อนอื่นฉันจะfetchใช้โทเค็นการเข้าถึงพร้อมข้อมูลจากโมดูล API ที่นำเข้าของฉัน
  2. หลังจากนั้นฉันจะตั้งค่าclientTokenคุณสมบัติthis.stateให้เท่ากับโทเค็นการเข้าถึงที่ได้รับ
  3. จากนั้นฉันจะเรียกใช้getPostsซึ่งควรส่งคืนการตอบกลับที่มีอาร์เรย์โพสต์ปัจจุบันจาก Product Hunt

ฉันสามารถที่จะตรวจสอบว่าโทเค็นการเข้าถึงจะถูกได้รับและที่this.stateจะได้รับเป็นของclientTokenสถานที่ให้บริการ ฉันยังสามารถตรวจสอบว่าgetPostsกำลังทำงานอยู่

ข้อผิดพลาดที่ฉันได้รับมีดังนี้:

{"ข้อผิดพลาด": "unauthorized_oauth", "error_description": "โปรดระบุโทเค็นการเข้าถึงที่ถูกต้องอ้างถึงเอกสาร API ของเราเกี่ยวกับวิธีการอนุมัติคำขอ API โปรดตรวจสอบให้แน่ใจว่าคุณจำเป็นต้องใช้ขอบเขตที่ถูกต้องเช่น \ สาธารณะส่วนตัว \ "สำหรับการเข้าถึงจุดปลายส่วนตัว"}

ฉันใช้ข้อสมมติว่าฉันไม่ผ่านโทเค็นการเข้าถึงอย่างถูกต้องในส่วนหัวการให้สิทธิ์ของฉัน แต่ดูเหมือนจะไม่สามารถคิดออกได้ว่าทำไม


2
ตามที่ระบุไว้ในSO ดังนั้นส่วนหัวมีจุดประสงค์ที่จะเป็นตัวพิมพ์เล็ก (เซิร์ฟเวอร์บางตัวเคารพสิ่งนี้, คนอื่นไม่ได้) ฉันแบ่งปันเพราะฉันถูกกัดโดยไม่รู้ว่าตัวเอง (และเสียเวลาพยายามแก้ไขปัญหา) โชคไม่ดีที่ โครงการตัวอย่างและบทความมากมายดูเหมือนจะไม่เคารพสิ่งนี้
tj

@tj ชื่อส่วนหัวไม่ตรงตามตัวพิมพ์ใหญ่ - เล็กและนั่นคือสิ่งที่ + คำตอบยอดนิยมที่ได้รับการยอมรับกล่าวไว้ในคำถามที่คุณเชื่อมโยง
แกนกลาง

คำตอบ:


195

ตัวอย่างการดึงข้อมูลด้วยส่วนหัวการให้สิทธิ์:

fetch('URL_GOES_HERE', { 
   method: 'post', 
   headers: new Headers({
     'Authorization': 'Basic '+btoa('username:password'), 
     'Content-Type': 'application/x-www-form-urlencoded'
   }), 
   body: 'A=1&B=2'
 });

4
มันไม่ทำงานสำหรับฉัน 'Authorization'หัวเงียบล้มเหลวที่จะแนบต่อวางเพลิง ฉันได้ลองรวมถึงcredentials: 'include'ในวัตถุทางเลือก
Ronnie Royston

7
@RonRoyston คุณกำลังดูตัวเลือกการโทรหรือไม่? หากจุดปลายทาง API ไม่ได้เปิดใช้งาน CORS (Access-Control-Allow-Origin: * หากเข้าถึงจากโดเมนอื่น) แสดงว่าอาจล้มเหลวเมื่อมีการเรียก OPTIONS
Cody Moniz

1
จุดสิ้นสุด api ไม่ได้เปิดใช้งาน CORS ดังนั้นอาจเป็นไปได้ว่าทำไมมันไม่ได้ผลสำหรับฉัน ขอบคุณ ฉันลงเอยด้วยการติดตั้งส่วนเสริมทุกที่สำหรับ Firefox และใช้งานได้
Ronnie Royston

3
หากพบปัญหาที่ @RonRoyston คุณต้องนำเข้าไลบรารี btoaซึ่งไม่ได้อยู่ในโหนด (เป็นพอร์ตของเบราว์เซอร์ lib) มิฉะนั้นการสร้างส่วนหัวรับรองความถูกต้องจะล้มเหลว เรากำลังประสบกับสิ่งเดียวกัน
Freewalker

2
developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetchต่อเอกสารต้องห่อส่วนหัวด้วยnew Headers()
Daniel Dubovski

67

ปรากฎว่าฉันใช้fetchวิธีไม่ถูกต้อง

fetch คาดว่าจะมีพารามิเตอร์สองตัว: จุดสิ้นสุดของ API และวัตถุทางเลือกซึ่งสามารถมีเนื้อหาและส่วนหัว

ฉันกำลังห่อวัตถุที่ต้องการภายในวัตถุที่สองซึ่งไม่ได้ผลลัพธ์ที่ต้องการ

นี่คือรูปลักษณ์ในระดับสูง:

fetch('API_ENDPOINT', OBJECT)  
  .then(function(res) {
    return res.json();
   })
  .then(function(resJson) {
    return resJson;
   })

ฉันจัดโครงสร้างวัตถุเช่น:

var obj = {  
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Origin': '',
    'Host': 'api.producthunt.com'
  },
  body: JSON.stringify({
    'client_id': '(API KEY)',
    'client_secret': '(API SECRET)',
    'grant_type': 'client_credentials'
  })

คุณสามารถให้รหัสที่ใช้งานได้ตอนนี้ได้ไหม ฉันพยายามใช้การดึงข้อมูลด้วยส่วนหัวการให้สิทธิ์และฉันไม่คิดว่ารหัสการรับรองความถูกต้องของฉันถูกส่งเป็นส่วนหัวเนื่องจากฉันได้รับการ401ตอบกลับ
GoldenBeet

2
ทำแล้วหวังว่าจะเป็นประโยชน์
Richard Kho

1
โอ้ฉันเคยอยู่บนไซต์ส่วนตัวของคุณด้วยตัวอย่างนั้น! นั่นเป็นวิธีที่ฉันสร้างแบบจำลองเหมืองในครั้งแรก ฉันคิดว่าปัญหาของฉันมันเป็นแค่ว่า URL ของฉันผิด มันจำเป็นต้องใช้/ในตอนท้ายว่าผมหายไป ...
GoldenBeet

1
ขอบคุณสิ่งนี้มีประโยชน์ เป็นที่น่าสังเกตว่าในขณะที่เอกสารการดึงข้อมูลชี้ให้เห็นว่าการดึงข้อมูลไม่ได้จัดการกับคุกกี้คุณสามารถเพิ่มคุกกี้ไปยังส่วนหัวด้วยรหัสนี้ได้เช่นกัน เพียงบันทึก uid และคีย์และทำสิ่งต่าง ๆ เช่น: var obj = {method: 'GET', ส่วนหัว: {'ยอมรับ': 'application / json', 'Content-Type': 'application / json', 'Cookie': 'uid =' + uid + ' key = '+ key});
ดัสติน

8

ฉันมีปัญหาที่เหมือนกันนี้ฉันใช้ django-rest-knox สำหรับโทเค็นการตรวจสอบสิทธิ์ ปรากฎว่าไม่มีอะไรผิดปกติกับวิธีการดึงข้อมูลของฉันซึ่งมีลักษณะเช่นนี้:

...
    let headers = {"Content-Type": "application/json"};
    if (token) {
      headers["Authorization"] = `Token ${token}`;
    }
    return fetch("/api/instruments/", {headers,})
      .then(res => {
...

ฉันกำลังวิ่งอาปาเช่

สิ่งที่แก้ปัญหานี้สำหรับผมก็เปลี่ยนWSGIPassAuthorizationไปใน'On'wsgi.conf

ฉันมีแอป Django ที่ติดตั้งบน AWS EC2 และฉันใช้ Elastic Beanstalk เพื่อจัดการแอปพลิเคชันของฉันดังนั้นในdjango.configฉันก็ทำสิ่งนี้:

container_commands:
  01wsgipass:
    command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'

0
completed = (id) => {
    var details = {
        'id': id,

    };

    var formBody = [];
    for (var property in details) {
        var encodedKey = encodeURIComponent(property);
        var encodedValue = encodeURIComponent(details[property]);
        formBody.push(encodedKey + "=" + encodedValue);
    }
    formBody = formBody.join("&");

    fetch(markcompleted, {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: formBody
    })
        .then((response) => response.json())
        .then((responseJson) => {
            console.log(responseJson, 'res JSON');
            if (responseJson.status == "success") {
                console.log(this.state);
                alert("your todolist is completed!!");
            }
        })
        .catch((error) => {
            console.error(error);
        });
};
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.