การทำลายการสืบค้น


19

ฉันรู้ว่าคุณเคยคิดเกี่ยวกับการทดลองและความยากลำบากในการประสบความสุขในชีวิตเป็นเว็บพร็อกซี่ สุจริตใครยังไม่ได้? วันนี้คุณได้รับมอบหมายให้ตระหนักถึงเป้าหมายนี้ (อย่างน้อยก็เป็นส่วนหนึ่งของมัน) เว็บไซต์ X ได้รับปริมาณการใช้งานจำนวนมากในแต่ละวันและกำลังมองหา PaaS (เห็นได้ชัดว่านี่หมายถึงพร็อกซีในรูปแบบบริการ) เนื่องจากมีผู้ใช้จำนวนมากที่ยืนยันการส่งผ่านข้อมูลที่ละเอียดอ่อนผ่านพารามิเตอร์การสืบค้น งานของคุณคือการลบพารามิเตอร์เคียวรีใด ๆ และที่สำคัญทั้งหมดออกจากคำขอก่อนที่จะส่งต่อคำขอผ่านไปยังปลายทางดั้งเดิม

อินพุต

  • ดีที่เกิดขึ้น URL แบบ HTTP แน่นอนที่เป็นไปตามหลักไวยากรณ์ URI ในRFC3986 มาตรา 3
    • คุณสามารถสันนิษฐานได้ว่าไม่มีชิ้นส่วน
    • ตัวอย่างรูปแบบย่อที่มีอะไรในวงเล็บเหลี่ยมหมายถึงทางเลือก: http[s]://[user:pass@]host.name.com[:port]/[?param1=value1&param2=value2...]
  • รายการพารามิเตอร์การสืบค้นที่จะถูกลบ

เอาท์พุต

HTTP URL ที่แก้ไขโดยไม่มีพารามิเตอร์ที่กำหนดในรายการอินพุต

ตัวอย่าง

http://example.com/ [foo]
> http://example.com/

http://example.com/?foo=bar []
> http://example.com/?foo=bar

http://example.com/ []
> http://example.com/

http://example.com/?foo=1&bar=2&baz=3 [foo,baz]
> http://example.com/?bar=2

http://example.com/?foo=1&bar=2&baz=3 [foo,bar,baz]
> http://example.com/

http://example.com/?foo&bar=2&baz= [foo,baz]
> http://example.com/?bar=2

http://example.com/?abc=1&def=2&baz=foo [foo,bar]
> http://example.com/?abc=1&def=2&baz=foo

http://example.com/?foobar=baz [foo]
> http://example.com/?foobar=baz

http://foo:foo@foo.com:8080/?foo=1&bar=foo [foo]
> http://foo:foo@foo.com:8080/?bar=foo

เกณฑ์การให้คะแนน

นี่คือดังนั้นคำตอบที่สั้นที่สุด (เป็นไบต์) ชนะ


1
ฉันสามารถรับ URL และพารามิเตอร์การสืบค้นแต่ละรายการแยกกันได้หรือไม่
seshoumara

1
สามารถ&ปรากฏที่ใดก็ได้นอกจากพารามิเตอร์?
Riley

ยังสามารถเช่นรหัสผ่านมี?? คำสั่งควรถูกเก็บไว้เหมือนเดิมหรือไม่
KarlKastor

@Riley ไม่หาก&เป็นส่วนหนึ่งของพารามิเตอร์การสืบค้นก็ควรจะ urlencoded อย่างถูกต้องเป็น%26
Poke

1
เห็นได้ชัดว่าได้http://foo:&foo=x@foo.com:8080/?foo=1&bar=fooรับอนุญาตจาก RFC สิ่งนี้น่าจะแก้ปัญหาที่มีอยู่เดิม : D (กฎคือ userinfo สามารถขยายได้ในรูปแบบ unreserved หรือ pct-escape หรือ sub-delims และ sub-delims สามารถมีได้&และ=)
n̴̖̋h16a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

คำตอบ:


6

GNU sed 98 96 88 80 77 74 69 59 54 (48 + 1 สำหรับ -r) 49

:;s,(.+)(=[^&]*[& ]|&)(.*)\1,\3 ,
t;s,[?&]? .*,,

รายการพารามิเตอร์ที่จะลบจะถูกคั่นด้วยช่องว่าง

$ echo 'http://example.com/?foo=1&bar=2&baz=3 foo bar baz' | sed -rf sed.txt
http://example.com/

$ echo 'http://example.com/?foo&bar=2&baz= foo baz' | sed -rf sed.txt
http://example.com/?bar=2

$ echo 'http://example.com/' | sed -rf sed.txt
http://example.com/

ในการแก้ไขรหัสปัจจุบันของคุณการทดสอบหลายอย่างจากคำถามของ OP ให้การติดตาม&หรือ?ตัวอักษรใน URL ที่ได้
seshoumara

@seshoumara ฉันไม่แน่ใจว่าฉันพลาดได้อย่างไร ... โชคดีที่มันมีความแตกต่างเพียง 1 ไบต์
Riley

ไม่พบรุ่นรหัส 96, 77 และ 59 ไบต์ในประวัติการแก้ไขของคุณ แก้ไข 7 ชื่อแสดง 10 ไบต์น้อยกว่าเมื่อเทียบกับการแก้ไข 6 แต่ไม่ได้เปลี่ยนรหัส แม้ว่าฉันจะ nitpicking กอล์ฟที่ยอดเยี่ยม!
seshoumara

1
@seshoumara ฉันคิดว่ามันรวมการแก้ไขบางอย่างเข้าด้วยกันเพราะพวกมันยังไม่บรรลุนิติภาวะ
Riley

@seshoumara ฉันคิดว่ามันรวมกันจริง ๆ เพราะฉันทำการแก้ไขหลายรายการภายใน 5 นาทีจากกัน
Riley

5

JavaScript (ES6), 62 60 ไบต์

f=
(s,a,u=new URL(s))=>a.map(e=>u.searchParams.delete(e))&&''+u
;
s.value=document.URL;
<div oninput=o.textContent=f(s.value,a.value.split`\n`)><input id=s><br><textarea id=a></textarea><pre id=o>

แก้ไข: บันทึก 2 ไบต์ขอบคุณ @Shaggy


คุณสามารถบันทึก 5 ไบต์ได้โดยปล่อย.hrefที่ท้าย
Shaggy

@Shaggy นั่นจะไม่ส่งคืนสตริง ... ฉันคิดว่าไม่ได้รับอนุญาต
Neil

มันขึ้นอยู่กับว่าคุณส่งออกมัน ตัวอย่างเช่นถ้าคุณใช้alertมันหรือใช้แทรกลงในโหนด (ข้อความ) ตามที่คุณมีมันจะให้hrefคุณสมบัติของวัตถุ หากคุณเข้าสู่คอนโซลแม้ว่ามันจะให้วัตถุเต็ม ดูซอนี้
Shaggy

1
@Shaggy Ah ดังนั้นฉันสามารถบันทึก 2 ไบต์ได้โดยการทำให้เป็นสตริงขอบคุณ
Neil

3

PHP, 90 ไบต์

<?=trim(preg_replace("#(?<=\?|&)(".join("|",$_GET[r]).")(=.*)?(&|$)#U","",$_GET[u]),"?&");

-11 ไบต์ถ้า? หรือ & ได้รับอนุญาตในตอนท้าย

รุ่นก่อนหน้า 140 ไบต์

<?=substr($u=$_GET[u],0,strpos($u,"?")+!!$j=join("&",preg_grep("#^(".join("|",$_GET[r]).")(=|$)#",explode("&",parse_url($u)[query]),1))).$j;

+2 ไบต์: ทางเลือกต้องถูกวงเล็บหรือ^/ (.*|$)จะเป็นส่วนหนึ่งของทางเลือกแรก / สุดท้าย
ติตัส

-2 ไบต์: .*ลบ หรือแทนที่(=.*|$)ด้วย\b(-5)
ติตัส

regexp จะมีลักษณะเช่นที่เป็นเหมือน#^foo|bar(=.*|$)# แต่มันควรจะเป็น#(^foo)|(bar=.*|bar$))# #(foo|bar)(=.*|$)#
ติตัส

@Titus คุณถูกความผิดของฉัน
JörgHülsermann

ดี! ฉันไม่คิดว่าจะยืนยัน นั่นเป็นเหตุผลที่ฉันกลับไปที่array_map(และฉันประหลาดใจว่ามันจะสั้นแค่ไหน)
ติตัส

2

PHP, 120 110 ไบต์

ด้วย preg_replace และฟังก์ชั่นอาร์เรย์: (ได้รับแรงบันดาลใจจากJörg )

<?=preg_replace(array_map(function($s){return"#(\\?|&)$s(=.*)?(&|$)#U";},array_slice($argv,2)),"\1",$argv[1]);

บันทึกเป็นไฟล์โทรด้วย php <scriptname> <uri> <parametername> <parametername> ...

ด้วย parse_str และ http_build_query (120 ไบต์):

parse_str(end($u=explode('?',$argv[1])),$a);for($i=$argc;$i-->1;)unset($a[$argv[$i]]);echo"$u[0]?".http_build_query($a);

ทำงานด้วย php -r <code> <uri> <parametername> <parametername> ...


parse_str? http_build_query? ฉันดีใจที่ได้เห็นคนที่ทำงานโดยใช้เครื่องมือที่เหมาะสมสำหรับงานแม้ในรหัสกอล์ฟ ข้อบกพร่องที่เกิดขึ้นเนื่องจากแบบสอบถาม URL / SQL / regexp / HTML นั้นเป็น "just strings" มีจำนวนมากเนื่องจากสามารถป้องกันได้อย่างง่ายดาย
Daerdemandt

อาจเป็นแรงบันดาลใจเพิ่มเติม ฉันได้รับคุณ
JörgHülsermann

@ ลินน์คุณไม่มีอะไรจะดีไปกว่าการสะกดรอยตามฉัน
ติตัส

2

Java 7, 127 ไบต์

String a(String a,String[]b){for(String c:b)a=a.replaceAll("(?<=[?&])"+c+"(=[^&]*)?(&|$)","");return a.replaceAll("[?&]$","");}

คำอธิบาย

String sanitize(String url, String[] params) {
    for (String param : params) {
        // please don't modify function parameters in real code
        url=url.replaceAll("(?<=[?&])" // Look for a leading ? or & but don't consume it
            + param                    // Consume the key of the query param (assuming key=value syntax)
            + "(=[^&]*)?"              // Consume the value of the query param if it exists
            + "(&|$)","");             // Consume the trailing & unless we're at the end of the url and replace with nothing
    }
    url = url.replaceAll("[?&]$",""); // If we remove all of the params then we'll have a trailing ? which needs to be removed
                                      // If we remove the last param only then we could have a trailing & which also needs to be removed
                                      // We will only run into one of these scenarios
    return url;
}

Ideone


สิ่งนี้ล้มเหลวสำหรับฉันโดยใช้ตัวอย่างที่ 4, 5, 6 และ 9 ของคุณ oO ฉันใช้ Java 8 อยู่แล้วดังนั้นอาจเป็นไปได้ แม้ว่าจะพยายามเทียบเคียง C # แล้ว แต่ก็ล้มเหลวในกรณีเดียวกันดังนั้น idunno
Yodle

1
ไม่เป็นไรสับสนตามที่ฉันทดสอบ
Yodle

2

C #, 377 336 330 328 ไบต์ (173 alt)

string n(string u,string[]r){var s=u.Split('?');if(s.Length<2)return u;var a=s[1].Contains("&")?s[1].Split('&'):new string[]{s[1]};int B=a.Length,i=0,C=i,c=B;for(;i<B;i++)foreach(var R in r)if(R==a[i].Split('=')[0]){a[i]="";c--;}var t=s[0];t+=c>0?"?":"";for(i=0;i<a.Length;i++)if(a[i]!=""){t+=a[i];C++;if(C!=c)t+="&";}return t;}

โปรแกรมเต็มรูปแบบ Ungolfed:

using System;
class a
{
    static void Main()
    {
        string input = Console.ReadLine();
        string url = input.Split(' ')[0];
        string r = input.Split(' ')[1];
        r = r.Replace("[", "").Replace("]","");
        string[] remove = r.Split(',');
        a b = new a();
        Console.WriteLine(b.n(url, remove));
    }
    string n(string u,string[]r)
    {
        var s=u.Split('?');
        if(s.Length<2)return u;
        var a=s[1].Contains("&")?s[1].Split('&'):new string[]{s[1]};
        int B=a.Length,i=0,C=i,c=B;
        for(;i<B;i++)
            foreach(var R in r)
                if(R==a[i].Split('=')[0])
                {
                    a[i]="";
                    c--;
                }
        var t=s[0];
        t+=c>0?"?":"";
        for(i=0;i<a.Length;i++)
            if(a[i]!="")
            {
                t+=a[i];
                C++;
                if (C!=c)t+="&";
            }
        return t;
    }
}

อาจจะไม่ได้มีประสิทธิภาพมากนัก แต่ก็ใช้งานได้ฉันคิดว่า

หรือมีวิธีแก้ปัญหา 173 ไบต์โดยใช้วิธีการของ @ Poke จาก Java ต้องมีการนำเข้าสำหรับ Regex แต่อาจจะไม่สั้นกว่านี้

using System.Text.RegularExpressions;string m(string a,string[]b){foreach(var c in b)a=Regex.Replace(a,$"(?<=[?&]){c}(=[^&]*)?(&|$)","");return Regex.Replace(a,"[?&]$","");}

2

ทับทิม, 146 140 127 119 116 113 ไบต์

แก้ไข 2: บันทึก 6 ไบต์โดยใช้$1, $2และ$*, และ 7 โดยเปลี่ยนx.split("=")[0]เป็นการx[/\w+/]
แก้ไข 3: บันทึก 6 ไบต์โดยใช้*แทน.join , บันทึก 2 ไบต์จากพื้นที่ที่ไม่จำเป็น
แก้ไข 4: บันทึก 3 ไบต์โดยปฏิรูประบบอินไลน์ (เปลี่ยน regex ให้เทียบเท่า$*[1][/([^?]*)\??(.*)/,1]และใส่ ตามที่ได้รับมอบหมายให้a)
แก้ไข 5: บันทึก 3 ไบต์โดยใช้($*[2].scan(r=/\w+/)&[x[r]])[0]แทน$*[2].scan(r=/\w+/).include?(x[r])

สมมติว่าอินพุตกับโปรแกรมเมื่อรันมัน:

a,b=$*[1][/([^?]*)\??(.*)/,1],$2.split("&").reject{|x|($*[2].scan(r=/\w+/)&[x[r]])[0]}*"&"
puts(b[0] ?a+"?"+b: a)

คำอธิบาย

a,b=$*[1][/([^?]*)\??(.*)/,1],$2.split("&")

นี้จะแยกวิเคราะห์ URL ที่กำหนดในบรรทัดคำสั่งและร้านค้าไม้ขีดไฟเข้าไปในและ $1 ยังส่งคืนการจับคู่ครั้งแรกเพื่อจัดเก็บภายใน$2$*[1][/([^?]*)\??(.*)/,1]aในขณะที่การจับคู่ที่สองเรียกว่า$2 ให้ชี้ไปที่ $ 1 และแยกbเป็นอาร์เรย์อาร์เรย์ ...

.reject { |x|

... ปฏิเสธทุกสิ่งที่ ...

    ($*[2].scan(r=/\w+/)&[x[r]])[0]

... มีสตริงก่อน '=' ที่รวมอยู่ในรายการชื่อที่กำหนดโดยพารามิเตอร์ที่สอง ... มันใช้งานได้เพราะเราสแกนหาคำ (เพื่อรับรายการ) จากนั้นรับคำก่อนหน้า=และดูว่า &คำที่อยู่ในรายการที่มี เนื่องจาก&ส่งคืนอาร์เรย์ว่างใน "ไม่พบ" (ชุดค่า null) เราใช้เคล็ดลับที่อธิบายด้านล่างเพื่อรับnilหากไม่มีองค์ประกอบในอาร์เรย์ มิฉะนั้นเราจะส่งคืนสตริงซึ่งนับว่าเป็นความจริงซึ่งปฏิเสธสตริงนั้น

}*"&"

... และเข้าร่วมสตริงที่เหลือพร้อมกับ '&'

ณ จุดนี้bเป็นสตริงการสืบค้น GET สำหรับ URL ดังนั้นเราเพียงแค่ต้องพิมพ์

puts(b[0] ?a+"?"+b: a)

วิธีนี้ใช้เคล็ดลับในทับทิม b[0]จะเป็นnilถ้า b เป็นอาร์เรย์หรือสตริงว่าง ดังนั้นหากความจริงของมัน(ไม่ใช่nilหรือfalse) ก็มีองค์ประกอบอย่างน้อยหนึ่งรายการในอาร์เรย์ดังนั้นเราจึงจำเป็นต้องใส่a+"?"+b URL ที่ถูกต้อง ไม่เช่นนั้นเราเพิ่งวางaเพราะไม่มีพารามิเตอร์ที่จะแสดง

หมายเหตุ: คำตอบนี้จะถือว่า ? ไม่สามารถทำได้ปรากฏที่ใดก็ได้ยกเว้นคั่น URL ออกจากแบบสอบถาม (ตามสิ่งที่ฉันอ่านจาก RFC ที่เชื่อมโยง)

นี่เป็นคำตอบกอล์ฟครั้งแรกของฉัน: D


2
ยินดีต้อนรับสู่ PPCG!
acrolith

1

จุดเล็ก ๆ , 46 ไบต์

รับ URL จาก stdin และพารามิเตอร์เคียวรีเพื่อลบออกจากบรรทัดคำสั่ง args

YgqR`\?.+`{s:J_@`^[^=]+`NIyFI@>a^'&[s&'?sJ'&]}

ลองออนไลน์!

คำอธิบาย:

 g               Local variable containing list of cmdline args
Y                Yank into global variable y so it's available inside the function
  q              Grab a line of stdin
   R`\?.+`{...}  Do a regex replace of everything from ? on, using a callback function:

s:J_@`^[^=]+`NIyFI@>a^'&[s&'?sJ'&]
                  @>a^'&            All but 1st char of match, split on &
                FI                  Filter on this function:
   _@`^[^=]+`                         Regex match: run of non = from beginning of string
                                      @ returns a list (here, of one item), so...
  J                                   Join to get a scalar
             NIy                      True if match not in y; false if in y
s:                                  Assign the filtered list to s
                        [        ]  Return a list containing:
                         s&'?       ? if s is nonempty, [] otherwise
                             sJ'&   s joined on &
                                    When used as a replacement, a list is first stringified
                                    (which, in the absence of flags, means concatenated)

1

PowerShell v3 +, 115 90 ไบต์

param($n,$z)$a,$b=$n-split'\?';($z|%{$b=$b-replace"(^|&)$_(=[^&]*)?(&|$)"});$a+"?"*!!$b+$b

รับอินพุต$nเป็น URL และ$zเป็นอาร์เรย์ของสตริงตามตัวอักษรเป็นพารามิเตอร์ที่จะลบ -splits URL อินพุตเปิด?เก็บครึ่งแรก$aและวินาทีเข้า$bและครั้งที่สองเข้ามา

ถัดไป$bเป็นสูตรใหม่โดยการวนซ้ำ$zดำเนินการ regex -replaceในคำค้นหาที่ถูกแบนแต่ละคำเพื่อลบออก จากนั้นเอาต์พุต$a(ไม่ได้แก้ไข) บวก a /ขึ้นอยู่กับว่า$bมีอยู่หรือไม่รวมถึง?ขึ้นอยู่กับว่า$xมีอยู่แล้วบวก `$ x


1

Pyth - 27 ไบต์

เคนนี่พูดถูกเมื่อเขาพูดถึงตัวบิวอินเพื่อแปลงร่างและกลับหัวกลับหางมันยากที่จะถูกต้อง

.sjK\?mj\&f!}hcT\=Qcd\&czKK

Test Suite


1

เรติน่า44 44ไบต์

Crossed-out 44 ยังคงเป็น 44 ขอบคุณ Martin สำหรับการแก้ไข

[?&](?>([^ =&]+))[^ &]*(?=.* \1( |$))| .*

/&
/?

uri param1 param2จะเข้าเช่น ลองออนไลน์!

คำอธิบาย

การแทนที่ครั้งแรกจะลบพารามิเตอร์ที่เหมาะสมออกจากสตริงการสืบค้น [?&](?>([^ =&+))[^ &]*ตรงกับ?หรือ&ชื่อพารามิเตอร์แบบเต็มและ (ทางเลือก) =และค่าการจัดเก็บชื่อพารามิเตอร์ในกลุ่มการจับภาพ 1 จากนั้น(?=.* \1( |$))เป็น lookahead ที่ตรวจสอบว่าชื่อพารามิเตอร์นั้นปรากฏในรายการพารามิเตอร์ที่จะลบหรือไม่ หากพารามิเตอร์ตรงกับเงื่อนไขเหล่านี้มันจะถูกลบออก (แทนที่ด้วยการแทนที่ว่าง)

การทดแทนไม่ทับซ้อนกัน (ต้องขอบคุณ lookahead) และดำเนินการต่อจากซ้ายไปขวา เมื่อถึงจุดสิ้นสุดของ URL .*สาขาจะจับคู่รายการพารามิเตอร์เพื่อลบและลบออกเช่นกัน

การแทนที่ครั้งที่สองจะทำให้แน่ใจว่าสตริงการสืบค้นใหม่เริ่มต้นด้วย?หากพารามิเตอร์ตัวแรกถูกลบ


ฉันคิดว่าสิ่งนี้จะลบพารามิเตอร์หากคำนำหน้าของพวกเขาปรากฏในรายการในตอนท้าย (เช่นลองretina.tryitonline.net/ ...... ) (?>...)วิธีหนึ่งในการแก้ไขปัญหานี้คือการห่อในกลุ่มที่ 1
Martin Ender

@MartinEnder TIL เกี่ยวกับคำสั่งย่อยที่ไม่ใช่การย้อนรอย ขอบคุณ!
DLosc

0

Java 7, 203 ไบต์

String f(String u,List p)throws Exception{String[]g=u.split("\\?",2);String s="";if(g.length>1)for(String q:g[1].split("&")){if(p.indexOf(q.split("=")[0])<0){s+=s.isEmpty()?"?":"&";s+=q;}}return g[0]+s;}

Ungolfed:

  String f(String u, List p) throws Exception {
    String[] g = u.split("\\?", 2);
    String s = "";
    if (g.length > 1) for (String q : g[1].split("&")) {
      if (p.indexOf(q.split("=")[0]) < 0) {
        s += s.isEmpty() ? "?" : "&";
        s += q;
      }
    }
    return g[0] + s;
  }

ฟังก์ชั่นนี้ผ่านการทดสอบทั้งหมด



0

PHP ไม่ใช่การแข่งขัน

Heck, PHP ถูกสร้างขึ้นมาเพื่อสิ่งนี้; ทำไมไม่ใช้ URL จริง

<?foreach($_GET[x]as$w)unset($_GET[$w]);
echo http,s[$_SERVER[SERVER_PORT]-443],"://",
$u=$_SERVER[PHP_AUTH_USER],($p=$_SERVER[PHP_AUTH_PW])?":$p":"","@"[!$u&!$p],
"$_SERVER[HTTP_HOST]$_SERVER[SCRIPT_NAME]?",http_build_query($_GET);

&x[]=x&x[]=<exclude1>&x[]=<exclude2>&...บันทึกไปยังแฟ้มโทรกับสตริงแบบสอบถามที่ต้องการของคุณบวก

อาจล้มเหลวในชื่อผู้ใช้และรหัสผ่าน (ขึ้นอยู่กับเบราว์เซอร์ของคุณลบพวกเขาหรือไม่)
จะ0ล้มเหลวถ้ารหัสผ่าน

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