Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

browsermob-proxy для скачивания файла с сервера


(Александр) #1

Доброго времени суток! Посмотрел видеоурок от Алексея Баранцева про browsermob-proxy. Там все примеры представлены на Java. Но в java я не ногой к сожалению и не могу понять как переписать пример на python для скачивания файла. Поможет может кто? Спасибо.

Пример кода на Java:

package ru.st.confetqa;

import net.lightbody.bmp.proxy.ProxyServer;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

public class Sample8_DownloadingFiles {

  @Test
  public void downloadingFiles() throws Exception {
    ProxyServer bmp = new ProxyServer(8071);
    bmp.start();

    HttpResponseInterceptor downloader = new FileDownloader()
        .addContentType("application/pdf");
    bmp.addResponseInterceptor(downloader);

    DesiredCapabilities caps = new DesiredCapabilities();
    caps.setCapability(CapabilityType.PROXY, bmp.seleniumProxy());

    WebDriver driver = new FirefoxDriver(caps);

    driver.get("http://localhost/test_download.html");
    driver.findElement(By.tagName("a")).click();

    String fileName = driver.findElement(By.tagName("body")).getText();
    assertTrue(new File(fileName).exists());

    Thread.sleep(30000);

    driver.quit();

    bmp.stop();
  }

  public static class FileDownloader implements HttpResponseInterceptor {

    private Set<String> contentTypes = new HashSet<String>();
    private File tempDir = null;
    private File tempFile = null;

    public FileDownloader addContentType(String contentType) {
      contentTypes.add(contentType);
      return this;
    }

    @Override
    public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
      String contentType = response.getFirstHeader("Content-Type").getValue();
      if (contentTypes.contains(contentType)) {
        String postfix = contentType.substring(contentType.indexOf('/') + 1);
        tempFile = File.createTempFile("downloaded", "."+postfix, tempDir);
        tempFile.deleteOnExit();

        FileOutputStream outputStream = new FileOutputStream(tempFile);
        outputStream.write(EntityUtils.toByteArray(response.getEntity()));
        outputStream.close();

        response.removeHeaders("Content-Type");
        response.removeHeaders("Content-Encoding");
        response.removeHeaders("Content-Disposition");

        response.addHeader("Content-Type", "text/html");
        response.addHeader("Content-Length", "" + tempFile.getAbsolutePath().length());
        response.setEntity(new StringEntity(tempFile.getAbsolutePath()));
      }
    }
  }
}

Ссылка на GitHub: Пример загрузки файла

Смежная тема:


(Mykhailo Poliarush) #2

Если есть возможность получить прямую ссылку на скачиваемый файл, тогда и browsermob-proxy не нужно. Просто используйте urllib

import urllib
urllib.urlretrieve ("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

А если все таки хотите переписать, то interceptor можно писать в двух вариантах (для java) через вызов метода, как Вы уже показали выше, а также через REST api с javascript

HTTP Request Manipulation
You can also POST a JavaScript payload to /:port/interceptor/request and /:port/interceptor/response using the REST interface. The functions will have a request/response variable, respectively, and a har variable (which may be null if a HAR isn’t set up yet). The JavaScript code will be run by Rhino and have access to the same Java API in the example above:

[~]$ curl -X POST -H ‘Content-Type: text/plain’ -d ‘request.getMethod().removeHeaders(“User-Agent”);’ http://localhost:9090/proxy/9091/interceptor/request
Consult the Java API docs for more info.

Так вот для python есть реализация только через REST api и в https://github.com/AutomatedTester/browsermob-proxy-py/blob/master/browsermobproxy/client.py реализуется с помощью двух методов

def response_interceptor(self, js):
    """
    Executes the javascript against each response
    :param js: the javascript to execute
    """
    r = requests.post(url='%s/proxy/%s/interceptor/response' % (self.host, self.port),
              data=js,
              headers={'content-type': 'x-www-form-urlencoded'})
    return r.status_code

def request_interceptor(self, js):
    """
    Executes the javascript against each request
    :param js: the javascript to execute
    """
    r = requests.post(url='%s/proxy/%s/interceptor/request' % (self.host, self.port),
              data=js,
              headers={'content-type': 'x-www-form-urlencoded'})
    return r.status_code

Ну и дальше пишите javascript и подключаете с помощью вышеупомянутых методов, вот примеры юнит тестов https://github.com/AutomatedTester/browsermob-proxy-py/blob/master/test/test_client.py

def test_request_interceptor_with_parsing_js(self):
    """
    /proxy/:port/interceptor/request
    """
    js = 'alert("foo")'
    status_code = self.client.request_interceptor(js)
    assert(status_code == 200)

(Александр) #3

Только вот я пытаюсь выполнить js код и он не выполняется. Не знаю почему. И еще данные функции возвращают только status_code, а мне хотелось бы доставать полный заголовок и путь куда файл сохраняется.


(Mykhailo Poliarush) #4

Ну тогда примеры кода в студию и вообще выдавайте побольше информации (мой же пример ответа информативный?! я точно также ожидаю такой же информативный вопрос, тогда движение происходит намного быстрее) и еще лучше выбрать в пример какой-то публичный сайт, чтобы можно было сделать и опубликовать публичный работающий для других код.