Mutilando a consulta


19

Eu sei que você sempre pensou nas provações e tribulações de experimentar as alegrias da vida como um proxy da web. Honestamente, quem não tem? Hoje você tem a tarefa de realizar esse objetivo (pelo menos uma parte dele). O site X recebe muito tráfego diariamente e está procurando um PaaS (isso claramente se refere ao Proxy como um Serviço) devido ao grande número de usuários que insistem em passar informações confidenciais por meio de parâmetros de consulta (os usuários são tolos). Sua tarefa é remover todos e quaisquer parâmetros de consulta confidenciais da solicitação antes de encaminhar a solicitação até seu destino original.

Entrada

  • Um URL HTTP absoluto bem formado que segue a gramática URI na Seção 3 do RFC3986 .
    • Você pode assumir que não há fragmento
    • Breve exemplo de formato, onde qualquer coisa entre colchetes denota opcional: http[s]://[user:pass@]host.name.com[:port]/[?param1=value1&param2=value2...]
  • Uma lista de parâmetros de consulta a serem removidos.

Resultado

A URL HTTP modificada sem os parâmetros definidos na lista de entrada.

Exemplos

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

Pontuação

Isso é , então a resposta mais curta (em bytes) vence.


11
Posso obter o URL e os parâmetros de consulta, cada um em linhas separadas?
seshoumara

11
Pode &aparecer em qualquer lugar que não seja entre parâmetros?
Riley

também pode, por exemplo, a senha conter um ?? Também a ordem deve ser mantida como era?
KarlKastor 19/09/16

@Riley No. Se &faz parte de um parâmetro de consulta, deve ser codificado corretamente como%26
Poke

11
Aparentemente, http://foo:&foo=x@foo.com:8080/?foo=1&bar=fooé permitido pelo RFC. Isso deve quebrar várias soluções existentes. : D (A regra é userinfo pode ser expandido como sem reservas ou PCT-fuga ou sub-delims, e sub-delims pode ter &e =)
n̴̖̋h̷͉a̷̭̿h̸̡̅ẗ̵̨d̷̰ĥ̷̳

Respostas:


6

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

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

A lista de parâmetros a serem removidos é separada por espaços.

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

Em sua atual edição do código, vários testes de pergunta de OP dar uma fuga &ou ?personagem no URL resultante.
seshoumara

@seshoumara Não sei bem como perdi isso ... Felizmente, é apenas uma diferença de 1 byte.
Riley

As versões de código de 96, 77 e 59 bytes não são encontradas no seu histórico de edições. O título da edição 7 mostrou 10 bytes a menos em comparação com a edição 6, mas o código não havia sido alterado. Estou indo embora, ótimo golfe!
seshoumara

11
@seshoumara Acho que combinou algumas das edições porque eram menores (apenas excluindo alguns caracteres).
Riley

@seshoumara Acho que realmente os combinou porque fiz várias edições em 5 minutos um do outro.
Riley

5

JavaScript (ES6), 62 60 bytes

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>

Editar: salvou 2 bytes graças a @Shaggy.


Você pode salvar 5 bytes, soltando .hrefno final.
Shaggy

@ Shaggy Isso não retornaria uma string ... Eu estava assumindo que isso não era permitido.
194 Neil

Depende de como você o produz. Por exemplo, se você alerto inserir ou usá-lo em um nó (texto), como você possui, ele fornecerá a hrefpropriedade do objeto. Se você registrá-lo no console, ele fornecerá o objeto completo. Veja este violino .
Shaggy

11
@ Shagy Ah, então eu posso definitivamente salvar 2 bytes, restringindo-o, obrigado.
194 Neil

3

PHP, 90 bytes

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

-11 bytes se? ou & é permitido no final

Versão anterior 140 bytes

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

+2 bytes: as alternativas devem estar entre parênteses ou ^/ (.*|$)farão parte da primeira / última alternativa.
Titus

-2 bytes: remover .*. ou substitua (=.*|$)por \b(-5).
Titus

O seu regexp será #^foo|bar(=.*|$)#idêntico ao #(^foo)|(bar=.*|bar$))#. Mas deveria ser #(foo|bar)(=.*|$)#.
Titus

@Titus Você está certo minha culpa
Jörg Hülsermann

legais! Não pensei em afirmações; foi por isso que voltei array_map(e fiquei surpreso com o quão curto pode acabar).
Titus

2

PHP, 120 110 bytes

com funções preg_replace e array: (inspirado em Jörg )

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

salvar em arquivo, ligue com php <scriptname> <uri> <parametername> <parametername> ...

com parse_str e http_build_query (120 bytes):

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

correr com php -r <code> <uri> <parametername> <parametername> ...


parse_str? http_build_query? Estou muito feliz em ver alguém trabalhando usando as ferramentas certas para o trabalho, mesmo no golfe de código. Os erros que surgem porque a consulta de URL / SQL / regexp / HTML são "apenas strings" são tão numerosos quanto facilmente evitáveis.
Daerdemandt

Talvez para mais inspiração. Eu tenho você
Jörg Hülsermann

@Lynn Você não tem nada melhor para fazer do que me perseguir?
Titus

2

Java 7, 127 bytes

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

Explicação

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


Isso falha para mim usando seus exemplos de quarto, quinto, sexto e nono oO, no entanto, estou usando o Java 8, então pode ser isso. Embora tentei o equivalente C # e falhou nos mesmos casos, então idunno.
Yodle 19/09/16

11
Deixa pra lá, estraguei tudo do jeito que eu estava testando.
Yodle 19/09/16

2

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

Programa completo não destruído:

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

Provavelmente não é muito eficiente, mas acho que funciona.

Como alternativa, há uma solução de 173 bytes usando o método @ Poke de Java. Requer uma importação para o Regex, portanto, provavelmente não pode ser mais curto.

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

Ruby, 146 140 127 119 116 113 bytes

editar 2: salvo 6 bytes, utilizando $1, $2e $*, e 7, alterando x.split("=")[0]para x[/\w+/]
editar 3: salvo 6 bytes, utilizando *em vez de .join, salvo 2 bytes de espaços desnecessários
editar 4: salvo 3 bytes por reformulação inline (mudou regex equivalente $*[1][/([^?]*)\??(.*)/,1]e colocar conforme atribuído a a)
editar 5: salvou 3 bytes usando em ($*[2].scan(r=/\w+/)&[x[r]])[0]vez de$*[2].scan(r=/\w+/).include?(x[r])

Supondo entrada para o programa ao executá-lo:

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

Explicação

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

Isso analisa a URL fornecida na linha de comando e armazena as correspondências em $1e $2. $*[1][/([^?]*)\??(.*)/,1]também retorna a primeira correspondência a ser armazenada dentro dela a, enquanto a segunda correspondência é referida como $2 deixar um ponto em $ 1 e analisar bem uma matriz de matrizes ...

.reject { |x|

... rejeitando tudo isso ...

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

... tem uma string antes do '=' incluída na lista de nomes fornecida pelo segundo parâmetro ... Isso funciona porque procuramos por palavras (para obter a lista) e depois obtemos a palavra antes de =, e verificamos se essa palavra está na lista com &. Como &retorna uma matriz vazia em "não encontrado" (o conjunto nulo), usamos o truque explicado abaixo para obter nilse não há elementos na matriz. caso contrário, retornamos uma string, que conta como verdade, que rejeita essa string.

}*"&"

... e junte as strings restantes com '&'

Neste ponto, bé a string de consulta GET para o URL. Assim, precisamos apenas imprimi-lo.

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

Isso usa um truque em rubi. b[0]será nilse b for uma matriz ou sequência vazia. Portanto, se for verdade , (não nilou false), haverá pelo menos um elemento na matriz, por isso precisamos colocar a+"?"+bo URL correto. caso contrário, apenas colocamos a, porque não há parâmetros para mostrar

Nota: esta resposta assume que ? não pode aparecer em qualquer lugar, exceto para delimitar o URL da consulta. (de acordo com o que eu li da RFC vinculada)

Além disso, esta é a minha primeira resposta de golfe: D


2
Bem-vindo ao PPCG!
acrolith 20/09/16

1

Pip , 46 bytes

Leva o URL de stdin e os parâmetros de consulta para remoção dos argumentos da linha de comando.

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

Experimente online!

Explicação:

 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 bytes

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

Recebe a entrada $ncomo a URL e $zcomo uma matriz literal de seqüências de caracteres como os parâmetros a serem removidos. -splits o URL de entrada ativado ?, armazena a primeira metade $ae a segunda dentro $b.

Em seguida, $bé reformulada fazendo um loop $z, executando uma regex -replaceem cada palavra de consulta banida para removê-las. Em seguida, saídas $a(não modificadas), mais um /dependendo se $bexiste, mais um ?dependendo se $xexiste, mais `$ x.


1

Pitão - 27 bytes

Kenny estava certo quando falou sobre o embutido para transformar e depois inverter, no entanto, será muito difícil de corrigir.

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

Conjunto de Teste .


1

Retina , 44 48 bytes

44 riscado ainda é 44. Obrigado a Martin pela correção.

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

/&
/?

Toma entrada como uri param1 param2. Experimente online!

Explicação

A primeira substituição exclui os parâmetros apropriados da string de consulta. [?&](?>([^ =&+))[^ &]*corresponde a um ?ou &, um nome completo de parâmetro e (opcionalmente) =e um valor, armazenando o nome do parâmetro no grupo de captura 1. Em seguida, (?=.* \1( |$))é um visor que verifica se esse nome de parâmetro aparece na lista de parâmetros a serem excluídos. Se um parâmetro corresponder a essas condições, ele será removido (substituído por uma substituição vazia).

As substituições não se sobrepõem (graças à cabeça de impressão) e prosseguem da esquerda para a direita. Ao chegar ao final da URL, a .*ramificação corresponde à lista de parâmetros a serem excluídos e a remove também.

A segunda substituição apenas garante que a nova sequência de consultas comece com ?se o primeiro parâmetro foi excluído.


Eu acho que isso também remove parâmetros se um prefixo deles aparecer na lista no final (por exemplo, tente retina.tryitonline.net/… ). Uma maneira de corrigir isso é agrupar o grupo 1 (?>...).
Martin Ender

@MartinEnder TIL sobre subexpressões sem retorno. Obrigado!
DLosc

0

Java 7, 203 bytes

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

Esta função passa em todos os testes.


0

Python, 75 81 112 bytes:

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

Uma função nomeada. Recebe entrada no formato

D(<String>,<Array>)

e gera uma string.

Repl.it com todos os casos de teste!


0

PHP, não competindo

Heck, PHP foi feito para isso; por que não usar o URL real?

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

Salve no arquivo, chame com sua string de consulta desejada mais &x[]=x&x[]=<exclude1>&x[]=<exclude2>&....

Pode falhar no nome de usuário e na senha (dependendo se o seu navegador os remove ou não).
Irá falhar se a senha é 0.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.