การบล็อกตำแหน่ง nginx สามารถจับคู่สตริงการสืบค้น URL ได้หรือไม่


23

บล็อกnginx สามารถจับคู่สตริงข้อความค้นหา URL ได้หรือไม่location

ตัวอย่างเช่นบล็อกตำแหน่งใดที่อาจตรงกับGETคำขอHTTP

GET /git/sample-repository/info/refs?service=git-receive-pack HTTP/1.1

ฉันเดา "location / git / sample-repository / info / refs? service = git-receive-pack" เป็น nginx เพียงทำการเปรียบเทียบสตริง
JosefScript

การเปรียบเทียบสตริงของ URL ทั้งหมดหรือเพียงบางส่วนก่อนเครื่องหมายคำถาม ( ?)?
Derek Mahar



1
การชี้แจงครั้งสุดท้ายขณะที่ฉันสะดุดปัญหานี้ด้วยตัวเอง: nginx.org/en/docs/http/request_processing.htmlระบุอย่างชัดเจน: "โปรดทราบว่าสถานที่ทุกประเภททดสอบเฉพาะส่วน URI ของบรรทัดคำขอโดยไม่มีอาร์กิวเมนต์ซึ่งทำได้เนื่องจากข้อโต้แย้ง ในสตริงการสืบค้นอาจได้รับในหลายวิธี "
Thomas Urban

คำตอบ:


37

การบล็อกตำแหน่ง nginx สามารถจับคู่สตริงการสืบค้น URL ได้หรือไม่

คำตอบสั้น ๆ : ไม่

คำตอบยาว : มีวิธีแก้ปัญหาเฉพาะหน้าหากเรามีบล็อกสถานที่เพียงหยิบมือเดียว

ต่อไปนี้เป็นตัวอย่างการแก้ปัญหาสำหรับ 3 ตำแหน่งบล็อกที่ต้องจับคู่สตริงข้อความค้นหาเฉพาะ:

server {
  #... common definitions such as server, root

  location / {
    error_page 418 = @queryone;
    error_page 419 = @querytwo;
    error_page 420 = @querythree;

    if ( $query_string = "service=git-receive-pack" ) { return 418; }
    if ( $args ~ "service=git-upload-pack" ) { return 419; }
    if ( $arg_somerandomfield = "somerandomvaluetomatch" ) { return 420; }

    # do the remaining stuff
    # ex: try_files $uri =404;

  }

  location @queryone {
    # do stuff when queryone matches
  }

  location @querytwo {
    # do stuff when querytwo matches
  }

  location @querythree {
    # do stuff when querythree matches
  }
}

คุณสามารถใช้ $ query_string, $ args หรือ $ arg_fieldname ทั้งหมดจะทำงาน คุณอาจจะทราบข้อมูลเพิ่มเติมเกี่ยวกับerror_page ในเอกสารอย่างเป็นทางการ

คำเตือน: โปรดตรวจสอบไม่ได้ที่จะใช้รหัสมาตรฐาน HTTP


1
วิธีการที่น่าสนใจ! ฉันขอแนะนำ$args ~ "service=git-send-pack"แทนได้$args = "service=git-send-pack"ไหม แบบฟอร์มนี้รองรับพารามิเตอร์แบบสอบถามหลายรายการ
Derek Mahar

1
stackoverflow.com/a/40313590/107158แสดงวิธีการที่ฉันติดตามเพื่อจัดการกับอาร์กิวเมนต์สตริงข้อความค้นหา เช่นเดียวกับคำตอบของคุณเหมืองใช้ifและ$arg_fieldnameแต่ใช้rewriteแทนและerror_page location @nameโปรดทราบว่าในตัวอย่างนั้นความพยายามของฉันที่ใช้@nameสำหรับพารามิเตอร์การแทนที่rewriteไม่ประสบความสำเร็จ
Derek Mahar

1
โดยวิธีการที่มันควรจะเป็นและ$args ~ $arg_somerandomfield =
Derek Mahar

1
ท่านสามารถใช้mapคุณสมบัติnginx เพื่อจุดประสงค์นี้ซึ่งเร็วกว่า
Tero Kilkanen

1
@PothiKalimuthu ขอบคุณสำหรับการชี้แจงนี้ สิ่งที่ผมได้กระทำในขณะเดียวกันคือการเปลี่ยนqueryพารามิเตอร์โดยหนึ่งในเส้นทาง URL เช่นนี้แทนfeedback/{auth_key} /feedback?auth_key=abcวิธีนี้ฉันไม่จำเป็นต้องใช้ifฉันสามารถกำหนดรูปแบบตำแหน่งโดยใช้regexและนั่นคือ
WM

4

ฉันรู้ว่าคำถามนี้มีอายุเกินหนึ่งปี แต่ฉันใช้เวลาสองสามวันสุดท้ายในการทำลายสมองของฉันในปัญหาที่คล้ายกัน ฉันต้องการการรับรองความถูกต้องที่แตกต่างกันและกฎการจัดการสำหรับ repos สาธารณะและส่วนตัวรวมถึงการผลักและดึง นี่คือสิ่งที่ฉันมาในที่สุดดังนั้นฉันคิดว่าฉันจะแบ่งปัน ฉันรู้ว่าifมันเป็นคำสั่งที่ยุ่งยาก แต่ดูเหมือนว่ามันจะใช้ได้สำหรับฉันดี:

# pattern for all repos, public or private, followed by username and reponame
location ~ ^(?:\/(private))?\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?$ {

    # if this is a pull request
    if ( $arg_service = "git-upload-pack" ) {

        # rewrite url with a prefix
        rewrite ^ /upload$uri;

    }

    # if this is a push request
    if ( $arg_service = "git-receive-pack" ) {

        # rewrite url with a prefix
        rewrite ^ /receive$uri;

    }

}

# for pulling public repos
location ~ ^\/upload(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}

# for pushing public repos
location ~ ^\/receive(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}

# for pulling private repos
location ~ ^\/upload\/private(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}

# for pushing private repos
location ~ ^\/receive\/private(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.