Mutilare la query


19

So che hai sempre pensato alle prove e alle tribolazioni di sperimentare le gioie della vita come proxy web. Onestamente, chi non l'ha fatto? Oggi hai il compito di realizzare questo obiettivo (almeno una parte di esso). Il sito Web X riceve molto traffico ogni giorno e sta cercando un PaaS (chiaramente questo si riferisce al proxy come servizio) a causa del gran numero di utenti che insistono sul passaggio di informazioni sensibili tramite parametri di query (gli utenti sono sciocchi). La tua attività è rimuovere tutti i parametri di query sensibili dalla richiesta prima di inoltrare la richiesta alla sua destinazione originale.

Ingresso

  • Un URL HTTP assoluto ben formato che segue la grammatica URI nella sezione 3 di RFC3986 .
    • Puoi presumere che non ci siano frammenti
    • Breve esempio di formato in cui qualsiasi cosa tra parentesi quadre indica facoltativo: http[s]://[user:pass@]host.name.com[:port]/[?param1=value1&param2=value2...]
  • Un elenco di parametri di query da rimuovere.

Produzione

L'URL HTTP modificato senza i parametri definiti nell'elenco di input.

Esempi

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

punteggio

Questo è , quindi vince la risposta più breve (in byte).


1
Posso ottenere l'URL e i parametri della query ciascuno su righe separate?
seshoumara,

1
Può &apparire in un luogo diverso da quello tra i parametri?
Riley,

inoltre, ad esempio, la password può contenere un ?? Inoltre, l'ordine dovrebbe essere mantenuto come prima?
KarlKastor,

@Riley No. Se &fa parte di un parametro di query, deve essere correttamente urlencodificato come%26
Poke

1
Apparentemente, http://foo:&foo=x@foo.com:8080/?foo=1&bar=fooè consentito dalla RFC. Questo dovrebbe spezzare un sacco di soluzioni esistenti. : D (La regola è userinfo può essere espansa come senza prenotazione o pct-escape o sub-delim, e i sub-delim possono avere &e =)
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Risposte:


6

GNU sed 98 96 88 80 77 74 69 59 54 (48 + 1 per -r) 49

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

L'elenco dei parametri da rimuovere sono separati da spazi.

$ 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/

Nella modifica del codice corrente, più test della domanda di OP forniscono un carattere finale &o un ?carattere nell'URL risultante.
seshoumara,

@seshoumara Non sono sicuro di come mi sia perso ... Fortunatamente è solo una differenza di 1 byte.
Riley,

Le versioni dei codici a 96, 77 e 59 byte non si trovano nella cronologia delle modifiche. Il titolo Modifica 7 mostrava 10 byte in meno rispetto alla modifica 6, ma il codice non era stato modificato. Sto scherzando, ottimo golf!
seshoumara,

1
@seshoumara Penso che abbia combinato alcune delle modifiche perché erano minori (eliminando solo alcuni caratteri).
Riley,

@seshoumara Immagino che li abbia effettivamente combinati perché ho fatto più modifiche entro 5 minuti l'una dall'altra.
Riley,

5

JavaScript (ES6), 62 60 byte

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>

Modifica: salvato 2 byte grazie a @Shaggy.


È possibile salvare 5 byte rilasciando .hrefalla fine.
Shaggy,

@Shaggy Che non restituirebbe una stringa ... Supponevo che non fosse permesso.
Neil,

Dipende da come lo hai prodotto. Ad esempio, se alertlo usi o lo inserisci, inseriscilo in un nodo (di testo), come hai, ti darà la hrefproprietà dell'oggetto. Se lo accedete alla console, tuttavia, vi darà l'intero oggetto. Vedi questo violino .
Shaggy,

1
@Shaggy Ah, quindi posso sicuramente salvare 2 byte stringendolo, grazie.
Neil,

3

PHP, 90 byte

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

-11 byte se? o & è consentito alla fine

Versione precedente 140 byte

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

+2 byte: le alternative devono essere tra parentesi o ^/ (.*|$)faranno parte della prima / ultima alternativa.
Tito,

-2 byte: rimuovi .*. o sostituire (=.*|$)con \b(-5).
Tito,

Il tuo regexp apparirà #^foo|bar(=.*|$)#identico a quello #(^foo)|(bar=.*|bar$))#. Ma dovrebbe essere #(foo|bar)(=.*|$)#.
Tito,

@Titus Hai ragione, colpa mia
Jörg Hülsermann,

simpatico! Non pensavo alle affermazioni; è per questo che sono tornato a array_map(e sono rimasto sorpreso da quanto a breve può risultare).
Tito,

2

PHP, 120 110 byte

con preg_replace e funzioni array: (ispirato a Jörg )

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

salva su file, chiama con php <scriptname> <uri> <parametername> <parametername> ...

con parse_str e http_build_query (120 byte):

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

Corri con php -r <code> <uri> <parametername> <parametername> ...


parse_str? http_build_query? Sono così felice di vedere qualcuno che lavora usando gli strumenti giusti per il lavoro, anche nel golf del codice. I bug che sorgono perché URL / query SQL / regexp / HTML sono "solo stringhe" sono numerosi e sono facilmente prevenibili.
Daerdemandt,

Forse per più ispirazione. I got You
Jörg Hülsermann,

@Lynn Non hai niente di meglio da fare che perseguitarmi?
Tito,

2

Java 7, 127 byte

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

Spiegazione

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


Questo non riesce per me usando i tuoi esempi 4, 5, 6 e 9 oO sto usando Java 8, quindi potrebbe essere. Anche se ha provato l'equivalente C # e ha fallito gli stessi casi, quindi idunno.
Yodle,

1
Non importa, ho incasinato il modo in cui lo stavo testando.
Yodle,

2

C #, 377 336 330 328 byte (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;}

Programma completo non golfato:

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;
    }
}

Probabilmente non molto efficiente, ma funziona credo.

In alternativa, esiste una soluzione da 173 byte che utilizza il metodo @ Poke di Java. Richiede comunque un'importazione per Regex, quindi probabilmente non può essere più breve.

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

Rubino, 146 140 127 119 116 113 byte

Modifica 2: salvato 6 byte utilizzando $1, $2e $*, e 7 cambiando x.split("=")[0]a x[/\w+/]
completa 3: salvato 6 byte utilizzando *invece .join, salvato 2 byte da spazi inutili
completa 4: salvato 3 byte riformulando linea (regex cambiato equivalenti $*[1][/([^?]*)\??(.*)/,1]e put come assegnato a a)
modifica 5: salvato 3 byte utilizzando ($*[2].scan(r=/\w+/)&[x[r]])[0]invece di$*[2].scan(r=/\w+/).include?(x[r])

Supponendo che l'input al programma sia in esecuzione:

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

Spiegazione

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

Ciò analizza l'URL indicato nella riga di comando e memorizza le corrispondenze in $1e $2. $*[1][/([^?]*)\??(.*)/,1]restituisce anche la prima corrispondenza da memorizzare all'interno a, mentre la seconda corrispondenza viene definita come $2 lasciare un punto a $ 1 e analizzare bin una matrice di array ...

.reject { |x|

... rifiutando tutto ciò ...

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

... avere una stringa prima del '=' che è incluso nell'elenco dei nomi dato dal secondo parametro ... Funziona perché scansioniamo le parole (per ottenere l'elenco) quindi prendiamo la parola prima del =, e vediamo se quella parola è nella lista con &. Poiché &restituisce un array vuoto su "non trovato" (il set null), utilizziamo il trucco spiegato di seguito per ottenere nilse non ci sono elementi nell'array. altrimenti restituiamo una stringa, che conta come verità, che rifiuta quella stringa.

}*"&"

... e unisci le stringhe rimanenti insieme a "&"

A questo punto, bè la stringa di query GET per l'URL. Quindi, dobbiamo solo stamparlo.

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

Questo usa un trucco in rubino. b[0]sarà nilse b è una matrice o stringa vuota. Quindi, se è vero , (no nilo false), allora c'è almeno un elemento nell'array, quindi dobbiamo inserirea+"?"+b l'URL corretto. altrimenti, ci limitiamo a mettere a, perché non ci sono parametri da mostrare

Nota: questa risposta presuppone che ? non possa apparire da nessuna parte se non per delimitare l'URL dalla query. (secondo quanto ho letto dalla RFC collegata)

Inoltre, questa è la mia prima risposta da golf: D


2
Benvenuti in PPCG!
acrolith,

1

Pip , 46 byte

Prende l'URL da stdin e i parametri della query per la rimozione dagli argomenti della riga di comando.

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

Provalo online!

Spiegazione:

 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 byte

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

Accetta l'input $ncome URL e $zcome una matrice letterale di stringhe come parametri da rimuovere. -splits l'URL di input è attivo ?, memorizza la prima metà in $ae la seconda in $b.

Successivamente, $bviene riformulato $zeseguendo un loop through , eseguendo una regex -replacesu ogni parola di query vietata per rimuoverli. Quindi, output $a(non modificato), più un a /seconda dell'esistenza $b, più un a ?seconda dell'esistenza $x, più `$ x.


1

Pyth - 27 byte

Kenny aveva ragione quando ha parlato dell'integrale da trasformare e poi invertire, tuttavia sarà molto difficile da correggere.

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

Test Suite .


1

Retina , 44 48 byte

Il 44 barrato è ancora 44. Grazie a Martin per la correzione.

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

/&
/?

Accetta input come uri param1 param2. Provalo online!

Spiegazione

La prima sostituzione elimina i parametri appropriati dalla stringa di query. [?&](?>([^ =&+))[^ &]*corrisponde a ?o &, un nome di parametro completo e (facoltativamente) =e un valore, memorizzando il nome del parametro nel gruppo di acquisizione 1. Quindi (?=.* \1( |$))viene visualizzato un lookahead che controlla se quel nome di parametro appare nell'elenco dei parametri da eliminare. Se un parametro soddisfa queste condizioni, viene rimosso (sostituito con una sostituzione vuota).

Le sostituzioni non si sovrappongono (grazie al lookahead) e procedono da sinistra a destra. Una volta raggiunta la fine dell'URL, il .*ramo corrisponde all'elenco dei parametri da eliminare e lo rimuove.

La seconda sostituzione si assicura solo che la nuova stringa di query inizi con ?se il primo parametro è stato eliminato.


Penso che questo rimuova anche i parametri se alla fine appare un prefisso nell'elenco (ad esempio, provare retina.tryitonline.net/… ). Un modo per risolvere questo problema è avvolgere il gruppo 1 in (?>...).
Martin Ender

@MartinEnder TIL sulle sottoespressioni senza backtracking. Grazie!
DLosc,

0

Java 7, 203 byte

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;
  }

Questa funzione supera tutti i test.


0

Python, 75 81 112 byte:

def Z(A,S):import re;F=A.rindex('/');print A[:F]+re.sub('|'.join(i+'(=\d?|&)&?'for i in S),'',A[F:]).strip('&?')

Una funzione denominata. Accetta input nel formato

D(<String>,<Array>)

e genera una stringa.

Repl.it con tutti i casi di test!


0

PHP, non in competizione

Diamine, PHP è stato creato per questo; perché non usare l'URL effettivo?

<?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);

Salva su file, chiama con la stringa di query desiderata plus &x[]=x&x[]=<exclude1>&x[]=<exclude2>&....

Potrebbe non riuscire a utilizzare nome utente e password (a seconda che il browser li rimuova o meno).
Fallirà se la password è 0.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.